Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Figure out if child element is outside parent element

Tags:

jquery

css

I am trying to figure out if a child element is visible in the parent element. By doing this I am testing if the width of the parent is bigger or smaller then the childs position().left.

Since I have many separate parent elements and child elements, I run each functions.

//Each p in instagram feed
jQuery('#instagram-feed .meta-data p').each(function(){

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

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

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

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

        } else {

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

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

    });

});

I have made a fiddle so you can see and test: http://jsfiddle.net/fprm7mgd/9/ (Make sure the three elements are horizontal to see the "bug")

enter image description here

The problem is that in the third parent element, it seems like position().left counts from the first parent, or above parent. Why does the link in the third parent becomes green? Since it is inside the parent it should be red... What have I done wrong?

like image 255
JoakimB Avatar asked Oct 26 '25 16:10

JoakimB


2 Answers

You could use jQuery(this).position().left - parent.position().left to calcualte the left of the a element, something like this:

//Each p in instagram feed
jQuery('#instagram-feed .meta-data p').each(function(){

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

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

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

            // If position os larger then width
            jQuery(this).css('color', 'green');
            console.log("Not inside element");

        } else {

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

        // ...

    });

});

See this working fiddle: http://jsfiddle.net/fprm7mgd/29/

like image 195
Fayyaz Naqvi Avatar answered Oct 28 '25 05:10

Fayyaz Naqvi


If you read the documentation of jQuery.position you will notice that the position is relative to the offset parent. The offset parent in your example is the <html> element and all left values are relative to that element.

The solution is to add a minor tweak to your CSS: make the paragraph elements position: relative.

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>
like image 39
Salman A Avatar answered Oct 28 '25 07:10

Salman A