Determine whether the child element extends beyond the boundaries of the parent element

I am currently working on determining whether a child element is visible within its parent element. To achieve this, I am comparing the width of the parent element to the position of the child element using position().left.

Given that I have multiple distinct parent and child elements, I am utilizing each functions.

//Iterating over each p element in the Instagram feed
jQuery('#instagram-feed .meta-data p').each(function(){

    // Storing the width of this p element
    var parentWidth = jQuery(this).width();

    // Iterating over each a element within this p
    jQuery(this).children('a').each(function(){

        // Comparing the width of the p element with the position of this a element
        if(parentWidth < jQuery(this).position().left) {

            // Changing text color to green if position exceeds width
            jQuery(this).css('color', 'green');
            console.log("Not inside element");

        } else {

            // Changing text color to red if position is within width
            jQuery(this).css('color', 'red');
            console.log("Inside element");
        }

        console.log(jQuery(this).position().left);

    });

});

I've created a fiddle for you to visualize and test: http://jsfiddle.net/fprm7mgd/9/ (Ensure the three elements are positioned horizontally to observe the "bug")

https://i.stack.imgur.com/Ah9c2.png

The issue arises in the third parent element where it appears that position().left is calculated from the first or higher-level parent element. Why does the link in the third parent turn green? It should be red since it's contained within the parent... What mistake have I made?

Answer №1

To determine the left position of the a element within its parent using jQuery, you can utilize the following code snippet:

// For every p in the Instagram feed
jQuery('#instagram-feed .meta-data p').each(function(){

    // Obtain the width of this p element
    var parentWidth = jQuery(this).width();
    var parent = jQuery(this);

    // Iterate through each a element within this p
    jQuery(this).children('a').each(function(){

        var elementLeft = jQuery(this).position().left - parent.position().left;
        
        // Compare the width of the p element with the position of this a element
        if(parentWidth < elementLeft) {

            // If the position is greater than the width
            jQuery(this).css('color', 'green');
            console.log("Not inside element");

        } else {

            // If the position is smaller than the width
            jQuery(this).css('color', 'red');
            console.log("Inside element");
        }

        // Additional logic here...

    });

});

View the demonstration on JSFiddle: http://jsfiddle.net/fprm7mgd/29/

Answer №2

Upon reviewing the documentation for jQuery.position, it becomes evident that the positioning is with respect to the offset parent. In this scenario, the offset parent is specified as the <html> element and all left values are in relation to this element.

To resolve this issue, a simple adjustment can be made to your CSS: ensure that the paragraph elements have position: relative set.

jQuery(window).on("load resize", function() {
  jQuery("#instagram-feed .meta-data p").each(function() {
    var parentWidth = jQuery(this).width();
    console.log("parent", this, "width", parentWidth);
    jQuery(this).children("a").each(function() {
      var childLeft = jQuery(this).position().left;
      console.log("child", this, "left", childLeft, "offset parent", this.offsetParent);
      if (parentWidth < childLeft) {
        jQuery(this).css("color", "green");
      } else {
        jQuery(this).css("color", "red");
      }
    });
  });
});
.meta-data {
  float: left;
  margin-right: 50px;
}
p {
  width: 160px;
  padding: 5px;
  white-space: nowrap;
  background: silver;
  display: inline-block;
  /* added */
  position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<div id="instagram-feed>
  <div class="meta-data>
    <p>fgdfgfdg fdgf df df <a href="#">link</a></p>
  </div>
  <div class="meta-data>
    <p>fgdfgfdg fdgf df df dsfsdf <a href="#">link</a></p>
  </div>
  <div class="meta-data>
    <p>fgdfgfdg fdgf <a href="#">link</a></p>
  </div>
</div>

Answer №3

  1. It is recommended to use the offset property instead of position for a safer approach. According to the documentation at http://api.jquery.com/offset/:

The .offset() method allows us to retrieve the current position of an element relative to the document. Contrast this with .position(), which retrieves the current position relative to the offset parent

  1. When using offset or position, you receive an object with properties like left and top. The key comparison should be between the anchor's left and the parent's calculated right position by adding the parent's width to its offset().left.

Example:

$('#instagram-feed .meta-data').each(function(){
    var parentRight = $(this).offset().left + $(this).width();
    $(this).find('a').each(function(){
        var self = $(this);
        if(self.offset().left > parentRight) {
            self.css('color', 'green');
        } else {
            self.css('color', 'red');
        }
    });
});

Demo Fiddle: http://jsfiddle.net/abhitalks/fprm7mgd/33/

Demo Snippet:

$('#instagram-feed .meta-data').each(function(){
    var parentRight = $(this).offset().left + $(this).width();
    $(this).find('a').each(function(){
var self = $(this);
        if(self.offset().left > parentRight) {
            self.css('color', 'green');
        } else {
            self.css('color', 'red');
        }
    });
});
.meta-data {
    float: left;
    margin-right: 50px;
    border: 1px solid #ddd;
}

p {
    width: 160px;
    padding: 5px;
    white-space: nowrap;
    background: silver;
    display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="instagram-feed">
    <div class="meta-data">
        <p>
            fgdfgfdg fdgf df df <a href="#">link</a>
        </p>
    </div>
    <div class="meta-data">
        <p>
            fgdfgfdg fdgf df df dsfsdf <a href="#">link</a>
        </p>
    </div>
    <div class="meta-data">
        <p>
            fgdfgfdg fdgf <a href="#">link</a>
        </p>
    </div>
</div>


An alternative solution would be to utilize the Javascript getBoundingClientRect method, which provides the size and position of an element in relation to the viewport.

var parents = document.querySelectorAll('.meta-data');
[].forEach.call(parents, function(elem) {
    var parentBounds = elem.getBoundingClientRect(), 
        anchor = elem.getElementsByTagName('A')[0], 
        anchorBounds = anchor.getBoundingClientRect()
    ;
    if (anchorBounds.left > parentBounds.right) {
        anchor.classList.add('red');
    } else {
        anchor.classList.add('green');
    }
});

Demo Fiddle 2: http://jsfiddle.net/abhitalks/n0ak4y7w/

Demo Snippet 2:

var parents = document.querySelectorAll('.meta-data');

[].forEach.call(parents, function(elem) {
    var parentBounds = elem.getBoundingClientRect(), 
        anchor = elem.getElementsByTagName('A')[0], 
        anchorBounds = anchor.getBoundingClientRect()
    ;
    if (anchorBounds.left > parentBounds.right) {
        anchor.classList.add('green');
    } else {
        anchor.classList.add('red');
    }
});
.meta-data {
    float: left;
    margin-right: 50px;
    border: 1px solid #ddd;
}

p {
    width: 160px;
    padding: 5px;
    white-space: nowrap;
    background: silver;
    display: inline-block;
}

.red { color: #f00; }
.green { color: #3c3; }
<div id="instagram-feed">
    <div class="meta-data">
        <p>
            fgdfgfdg fdgf df df <a href="#">link</a>
        </p>
    </div>
    <div class="meta-data">
        <p>
            fgdfgfdg fdgf df df dsfsdf <a href="#">link</a>
        </p>
    </div>
    <div class="meta-data">
        <p>
            fgdfgfdg fdgf <a href="#">link</a>
        </p>
    </div>
</div>

Answer №4

The ultimate solution:

//This function is designed to work effectively when the margins and paddings are balanced on both sides.
function excludeFromTabIndex(element, ellipsisWidth){

    var initialEllipsisWidth = ellipsisWidth;
    if (initialEllipsisWidth === undefined || initialEllipsisWidth === null) {
        initialEllipsisWidth = 0;
    }

    jQuery(element).each(function(){
        var calculatedMargin = (jQuery(this).outerWidth(true) - jQuery(this).width()) / 2;
        calculatedMargin = calculatedMargin + initialEllipsisWidth;
        var parentRightValue = (jQuery(this).position().left + jQuery(this).outerWidth(true)) - calculatedMargin;

        jQuery(this).find('a').each(function(){
            if((jQuery(this).position().left) > parentRightValue) {
                jQuery(this).attr('tabindex', '-1');
            } else {
                if ( jQuery(this).attr('tabindex') === '-1') {
                    jQuery(this).removeAttr('tabindex')
                }
            }
        });

    });

};

//Call the function
jQuery(document).ready(function(){
    excludeFromTabIndex('#instagram-feed .meta-data p');
});

//For responsive design
jQuery(window).resize(function () {
    excludeFromTabIndex('#instagram-feed .meta-data p');
});

This script handles padding and margin issues by assuming equal values on left and right sides. Pixel-based margin and padding calculations are necessary since other units like percentages or ems cause inconsistencies.

It executes initially and upon resizing for responsiveness. Additional elements can easily be incorporated using parameters. The function now accepts an ellipsis width parameter for more precise calculations.

With this code snippet, you can implement text truncation with CSS and prevent overflowing links from being included in the tab index, improving accessibility.

http://jsfiddle.net/fprm7mgd/46/

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using AngularJS to auto-populate additional fields after selecting an option from the typeahead autocomplete feature

Just starting with AngularJS and finally figured out how to implement Auto-complete in Angularjs. Now, when a user selects a value from the auto-complete, I want other fields to be populated based on that selection. For example, upon loading the screen, d ...

What is the solution for resolving the problem of the cursor jumping to the end when converting numbers in JavaScript?

After exploring the inquiries regarding converting digits in JavaScript, such as What's the solution and the right way to convert digits in JavaScript? and How to convert numbers in JavaScript, and problems with commands to remove non-numeric characte ...

Unbinding or undoing an 'onclick' event when another 'onclick' event is triggered

I am facing an issue where clicking on elements with 'onclick' functions works as expected, but when I click on a different element with another 'onclick' function, the first one remains active. What I actually want is for the previous ...

Achieving consistent height for Grid items in Material-UI

I'm looking to achieve equal heights for these grid items without distorting them. Here's the current layout: This is how I would like it to look: My challenge is that adjusting the image width manually makes it non-responsive. Since users may ...

Techniques for adjusting the dimensions of a select dropdown using CSS

Is there a way to control the height of a select dropdown list without changing the view using the size property? ...

Displaying a collapsible table directly centered within the table header

I am having trouble centering my table header in the web browser page. When I click the "+" button, the data is displayed beneath the table header, but I want the collapsible table to be centered directly below the header. I have tried making changes in CS ...

Utilizing jquery and ajax to showcase a series of images prior to uploading them

I have been attempting to create a feature that allows for the preview of multiple images before uploading them to my website. Unfortunately, it's not working as expected and I am unable to identify any errors in the console. Below is the JavaScript c ...

Tips for enabling scrolling on mobile devices

Hello there, I'm facing an issue with scrolling on my website when viewed on mobile devices. Even though I have set the div height to 100%, it appears as 'auto' on mobile screens. As a result, when the text exceeds the screen height, it bec ...

Executing a function while adjusting a range slider

Having an <input type="range"> element on my website presents a particular challenge. To handle changes in this element, I am using the following function: $("#selector").bind("change", function() { //perform desire ...

Create an input field with a dynamic and exclusive identifier using the DataTables plugin

I am having trouble creating unique IDs for each input field based on the number of rows Here is the code snippet: $(document).ready(function() { var oTable = $('#jsontable').dataTable(); //Initialize the datatable $.ajax({ url ...

What is the best way to create a <div> that will automatically start a new line based on the user's input?

Is it possible to create a div that automatically inserts a new line for each new line in the code it detects when typing? For example, if I type: <div> Hello, World! How are you doing today? </div> This would normally be displayed as ...

Transferring a row name from PHP to AJAX using jQuery - the complete guide

In my current project, I have a table that displays details fetched from the database. if(mysql_num_rows($sql) > 0) { $row_count_n = 1; while($rows = mysql_fetch_assoc($sql)) { extract($rows); $options1 = select_data_as_options( ...

Using the identical code, Wicked PDF generates distinct reports on separate computers

While utilizing Ruby on Rails to render a PDF using WickedPDF and sending it via email, I encountered an unexpected issue. The same code is present on two separate computers, both with up-to-date versions synced from GitHub. However, the generated PDF repo ...

Customized selection groups for dropdown menu based on alphabetical order

I am dynamically generating a select list from an array of data and I want to group the options alphabetically. For example, here is the data: data = [ ['bcde','21254'], ['abcd','1234'], ['abcde',' ...

Transmitting a plethora of information using jQuery

Here's the code I currently have for sending data: var test={imagename:"apple.jpg",x:"13",y:"33"}; $.ajax({ type: "POST", url: "some.php", data: test, success: function(response){ console.log(response); } }); ...

"Enhance your website with the magic of jQuery magnific-popup

Is there a way to add an additional button to the jquery magnific-popup component that can close the dialog box? I am currently utilizing this component to insert descriptions for photos, so I need a submit button that will successfully add the descriptio ...

Customize the colors of the arrows in Bootstrap's carousel

There seems to be a simple solution that I'm missing here. I have images with white backgrounds and I want to customize the arrows on Bootstrap's Carousel to make them more visible. I need help changing the color of the arrows (not the background ...

Tips for displaying an edit action icon when hovering over specific text

Looking for a way to display or hide the edit icon when hovering over specific text? Take a look at this snippet of HTML code: <ul> <li> <a id="pop" href="javascript:;;" data-content="test Desc" data-id="123"> &l ...

Navigate within the div by scrolling in increments of 100%

I am facing an issue with a div that contains multiple children set to 100% height. My goal is to scroll exactly the height of one child (which is also 100%) on each scroll. However, I am struggling to prevent scrolling multiple steps at a time. I have tri ...

Stop the scrolling behavior from passing from one element to the window

I am facing an issue with a modal box window that contains an iframe. Inside the iframe, there is a scrollable div element. Whenever I try to scroll the inner div of the iframe and it reaches either the top or bottom limit, the browser window itself start ...