Chrome doesn't update styles when last child changes

Problem

Styles are not updated when last-child changes due to the addition of additional elements dynamically using JavaScript.

Example

Click "Add additional blocks" in the snippet below. When new blocks are added, the fourth .block element ("Control block 4") will not have a lower red border, even if it is no longer the last element in #container .

 $("#addMore").one("click", function() { $("#container").append($("#container").html()); $(this).remove(); }); 
 .block { border-bottom: 1px solid red; counter-increment: block; margin: 20px 0; position: relative; } .block:after { content: " " counter(block); } .block:last-child { border-bottom: 0; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="container"> <div class="block">Test block</div> <div class="block">Test block</div> <div class="block">Test block</div> <div class="block">Test block</div> </div> <div id="addMore">Add more blocks</div> 

Js fiddle

Expected Behavior

After clicking the "Add more blocks" button, all .block elements should have a lower red frame, except for the eighth block ("test block 8").

Browsers done

Tested and not working in Chrome 55.0.2883.87 m. The expected behavior returned by IE 11.0.9600.18538 and Firefox 50.1.0.


Can this be solved without:

  • Using JavaScript (i.e. dynamically adding a class that removes the red border from the last element)?
  • Restructuring CSS to not use last-child (i.e. instead of first-child and border-top )?
+6
source share
3 answers

As a workaround, you can replace the last-child pseudo-class with nth-last-child(1) , which does the same as last-child, but does not affect the error.

 $("#addMore").one("click", function() { $("#container").append($("#container").html()); $(this).remove(); }); 
 .block { border-bottom: 1px solid red; counter-increment: block; margin: 20px 0; position: relative; } .block:after { content: " " counter(block); } .block:nth-last-child(1) { border-bottom: 0; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="container"> <div class="block">Test block</div> <div class="block">Test block</div> <div class="block">Test block</div> <div class="block">Test block</div> </div> <div id="addMore">Add more blocks</div> 
+2
source

I tested in Chrome 55.0.2883.87, and it puzzles me - obviously a mistake.

Even when I used .clone() instead of .html() , the problem is there:

 $("#container").append($("#container > .block").clone()); 

A possible fix might be to force container re-rendering - I used this for reprocessing:

 $('#container').hide().show(0); 

See the demo below:

 $("#addMore").one("click", function() { $("#container").append($("#container > .block").clone()); // fix: by forcing re-rendering $('#container').hide().show(0); $(this).remove(); }); 
 .block { border-bottom: 1px solid red; counter-increment: block; margin: 20px 0; position: relative; } .block:after { content: " " counter(block); } .block:last-child { border-bottom: 0; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="container"> <div class="block">Test block</div> <div class="block">Test block</div> <div class="block">Test block</div> <div class="block">Test block</div> </div> <div id="addMore">Add more blocks</div> 
+1
source

Playing a bit with this problem, hints at the presence of some error in the Chrome browser.

However, I noticed that if we use border-top instead of border-bottom , then it works correctly.

CSS

 .block:not(:first-child) { border-top: 1px solid red; } 

 $("#addMore").one("click", function() { $("#container").append($("#container").html()); $(this).remove(); }); 
 .block { counter-increment: block; padding: 20px 0; position: relative; margin-bottom: 1px; } .block:after { content: " " counter(block); } .block:not(:first-child) { border-top: 1px solid red; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div id="container"> <div class="block">Test block</div> <div class="block">Test block</div> <div class="block">Test block</div> <div class="block">Test block</div> </div> <div id="addMore">Add more blocks</div> 
+1
source

Source: https://habr.com/ru/post/1013904/


All Articles