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

Angular 5: Transforming and Concealing CSS Class Names

Can CSS selectors be renamed or obfuscated in an Angular CLI project? Many top websites like Google and Facebook use randomized CSS names for various reasons, such as preventing website scripting through targeting static class names. I would like to imple ...

What is the recommended way to adjust the width of a paper-textarea element in Polymer 1.0?

Is there a way to adjust the width of a paper-textarea? I have tried using CSS selectors within Polymer 1.0 style tags, but it does not seem to be effective. The paper-textarea element is made up of paper-input-container. I attempted the following approach ...

Interactive calendar feature displaying events upon hovering over a date

I need some assistance with displaying a drop-down list on full calendar events when hovering over the events. Can someone provide guidance? Here is a glimpse of what I currently have: I've attempted setting the z-index, but I can't seem to get ...

How can a script be properly embedded into an HTML document?

Currently, I am facing an unusual issue with the script tags in my Django project. My layout.html file includes Jquery and Bootstrap in the head section. Using Jinja, I extended layout.html to create a new file called main.html. In main.html, I added a new ...

Jquery cloning problem: Original element vanishes unexpectedly in certain cases

My code clones an element and inserts it in the right place, but sometimes the original disappears. Can you help me figure out what's wrong? The main purpose of this script is to show a specific element at the top of the page whenever there is a hash ...

Internet Explorer 9 users experience a sudden blank page display

Are there any effective methods for diagnosing why a page suddenly becomes blank in Internet Explorer? I am aware that switching to Compatibility Mode 7 is an option, however dealing with the quirks of IE7 can be even more challenging. ...

concealing components during screen adjustments

There are 3 identical <div>s available: <div class="box">Hello World!</div> <div class="box">Hello World!</div> <div class="box">Hello World!</div> I need these <div>s to ...

What is the Best Method to Retrieve the Desired Data from a YQL Query using a Callback Function?

I successfully implemented a callback function that retrieves titles related to a user-submitted string in a text input box. However, I am struggling with how to extract only the titles from the returned callback function after submitting a search term. C ...

Is it possible to make changes to local storage data without impacting the rest of the data set?

I am looking for a way to modify specific data in the local storage without affecting any other stored information. However, I have encountered an issue where editing values works correctly for the first three attempts, but on the fourth try, it seems to ...

The jQuery selector fails to refresh after the dynamic insertion of new elements

My selector is: $('section#attendance input:last') However, I add another input to section#attendance. I want the selector to target that new element since it should select the last element due to :last. However, for unknown reasons, it does no ...

A conflict with the Ajax file is causing an automatic logout

In my Rails application, there is a page with a table that uses partial AJAX to increase the capacity attribute in a time entity. You can view the visual representation of the table here. By clicking the plus/minus button, the capacity attribute increases ...

How do I resolve the issue of not being able to display the value for the slider range?

What do I need to do if I am unable to print the value for a slider range in my code? <?php $salary=array( 'type'=>'range', 'name'=>&apo ...

What are the steps to implement infinite scrolling in a Vue.js application?

Currently, I am attempting to implement an infinite horizontal scroll section in vuejs for a selection of products. However, I am facing difficulties achieving the infinite effect. My approach so far involved removing the card that goes out of view and add ...

How to Make a Doughnut Chart Using CSS

For a while now, I've been working on filling in 72% of a circle with a hole cut out of the middle. Throughout this process, I have been consulting different resources - like this method for calculating and this one for other aspects. However, I’ve ...

Responsive HTML5 audio player adjusts size when viewed on mobile devices

I am facing a challenge with an HTML5 Audio player. It looks fine on desktop but behaves strangely on mobile devices. While the width remains intact, it repositions itself and floats over the element it is contained within. How can I prevent this repositio ...

The content's div is not extending completely in the horizontal direction

Just starting out with tailwind CSS and struggling a bit with the design aspect due to my lack of CSS skills. Need some assistance troubleshooting my layout, particularly in making sure the div container stretches to fit the screen size properly. The spec ...

"Implementing JavaScript Validation for Textboxes: A Step-by-Step Guide

I need some help with restricting the input of a textbox within a gridview to only 'X' or 'O'. I am not very familiar with javascript, so any guidance on how to accomplish this would be greatly appreciated. It's worth noting that t ...

Tips on clearing all cookies using jQuery

Similar Question: Clearing all cookies with javascript I'm looking to create a checkbox that can clear all previously stored cookies in my forms with just one click. How can I achieve this using the jquery cookie plugin? I've searched both K ...

Tips for utilizing JSON and ajax smoothly without encountering any errors

I am attempting to retrieve JSON data from an external PHP file using AJAX and populate it into a dropdown list. After successfully setting up XAMPP with Apache and Mysql, I managed to make everything work for one JSON object. However, when I tried adding ...

The jQuery remove function will only take effect on the second click following an AJAX request

I'm facing an issue with my jQuery code where two divs contain lists of links, triggering AJAX calls to append JSON data to a separate div. Upon clicking a link, the corresponding link div should hide. There's also a third div with the class "pan ...