17

I'm trying to set style for a <div> following an empty <ul>.

This is simple code i'm currently testing: (OS is win7)

Basic jsFiddle DEMO

HTML:

<button class="btnAdd">add new LI</button>
<button class="btnRemove">remove last LI</button>
<ul></ul>
<div>Should be red if UL is empty</div>

CSS:

ul:empty + div {
    color:red;    
}

jQuery: (not relevant to issue, just for testing purpose)

$('.btnAdd').on('click', function () {
    $('ul').append('<li>LI</li>');
});

$('.btnRemove').on('click', function () {
    $('ul').find('li').last().remove();
});

Expected behaviour:

In all major browsers, when adding element to <ul>, style set for empty <ul> following <div> shouldn't be applied. When removing all <li>, style should be reapplied to targeted <div>.

Current behaviour:

  • Firefox handles it with no problem, get expected result.
  • Chrome removes red color for following DIV when UL is no more empty, but doesn't reapply it when UL is empty again (removing all LIs from UL)
  • IE10/11 just apply CSS :empty pseudo-class as by default, not reacting to any content added or removed

Googling it, i've find some workarounds but most seem outdated and none fix issue here, none i can't find at least.

For chrome, i've found that setting a CSS rule :empty for UL fixes it, but really i don't know what's going on: ul:empty {} (ya this is an empty CSS rule?!) <-- I guess now it forces an UI repaint on chrome ?!

Fixed jsFiddle for chrome

Unfortunatley, this doesn't fix behaviour on IE10/11.

So anyone knows a way to make it works on all major browsers???

UPDATE 1:

Seems like bug is related to next sibling selector +, even using ~ doesn't give consistent result on chrome. But if applying style directly to :empty element, all seems to work correctly on all browsers: http://jsfiddle.net/EyEa7/ But my goal here is to target sibling element of :empty element, not the empty element directly.

UPDATE 2:

Forcing an UI redraw fixes it on all browsers, e.g using $('body').hide().show(0); once content has been updated: See DEMO forcing redraw

But, i'd really more appreciate a fix which doesn't involve any javascript code.

The question now could be:

  • How can i force IE10/11 to repaint UI using only CSS? (hoping this is a relevant question regarding this issue)
A. Wolff
  • 74,033
  • 9
  • 94
  • 155
  • Unfortunately IE is always lagging behind. Your best bet would be to use features like this to enhances the user experience for the browsers that support such niceties, But don't rely on them for functionality as there will always been someone browsing the site in IE7/8. Your chrome fix works for me on Chrome 34 – Ashley Medway Mar 31 '14 at 12:31
  • @AshleyMedway I'm not looking to support any browsers which don't support natively `:empty` pseudo-class. I'm just looking to get it works as expected on relevant browsers. Anyway, thx for your input – A. Wolff Mar 31 '14 at 12:38
  • @A.Wolff i tested it in ie its work first time but when we add li then its not working right is it same with you? – Just code Mar 31 '14 at 12:45
  • Just noted, if `~` used then after adding or removing a element, we need to click on the document/page to see the default behavior of `:empty` on Chrome, Win 8. – Mr_Green Mar 31 '14 at 12:46
  • @DholakiyaAnkit If i understand correctly you, ya, i have same behaviour on IE10/11 – A. Wolff Mar 31 '14 at 12:47
  • @Mr_Green Using `ul:empty ~ div`, TABLE needs to lose focus on first LI added to 'update' style. That's quite strange! EDIT: didn't see your updated comment, same behaviour here on Win7 – A. Wolff Mar 31 '14 at 12:50
  • http://jsbin.com/tacuxori/1/edit Please check this url it will work wait for this 10 or more seconds. – Just code Mar 31 '14 at 12:55
  • @DholakiyaAnkit Which part is the fix?! In IE, now it works in some way even looks like same bug as using `ul:empty ~ div` selector in chrome, UL needs to loose focus to update style, strange! http://jsbin.com/tacuxori/2/edit – A. Wolff Mar 31 '14 at 12:57
  • Ya actually @A.Wolff i don't know much information about this.But i googled it and find some tools so i tried it. – Just code Mar 31 '14 at 12:59
  • 1
    @DholakiyaAnkit Indeed, looks like related to jsbin vs jsfiddle and maybe how is handled iframe or maybe auto run script mode on jsbin, don't know. http://jsbin.com/tacuxori/3/edit – A. Wolff Mar 31 '14 at 13:10
  • 1
    This seems not to depend on iframe, jsFiddle or jsbin particularity : http://fiddle.jshell.net/Je6UY/3/show/light/ – Brewal Mar 31 '14 at 14:01
  • 2
    You can force a repaint with CSS3 `animate`. Check this answer http://stackoverflow.com/questions/22011139/google-fonts-are-not-rendering-on-google-chrome/22025804#22025804 maybe it's applicable for your situation – pstenstrm Mar 31 '14 at 14:04
  • There is actually a similar question : http://stackoverflow.com/questions/9443500/empty-pseudoclass-when-adding-dynamic-content – Brewal Mar 31 '14 at 14:04
  • @Brewal Thx for the link but i already tested it and doesn't apply here unfortunately, as i tested it :( – A. Wolff Mar 31 '14 at 14:05
  • 1
    @pstenstrm Thx, i'm testing it. UPDATE: not works on IE :( Fixes it on chrome but even empty CSS rule fixes it on chrome – A. Wolff Mar 31 '14 at 14:12
  • 3
    @Ashley Medway: "Unfortunately IE is always lagging behind." Likewise with Chrome. It's not just IE anymore, hasn't been for a while. Both browsers clearly need some way to force a repaint here even though repaints should be performed automatically based on changes to the DOM. And this isn't even the only problem that Chrome has with sibling combinators. – BoltClock Mar 31 '14 at 15:06
  • @pstenstrm It was the right way to force repaint. I had tried the linked solution but didn't work (of course i had removed prefix for animation). But indeed using animation was a working way, so thank to you! – A. Wolff Mar 31 '14 at 21:12

1 Answers1

7

Something like this will work, but it's not particularly pretty:

ul:empty {}

ul:empty + div {
    color: red;
}

ul + div {
    animation: repaint 1000s infinite linear;
}

@keyframes repaint {
    from { zoom: 1; }
    to { zoom: 0.99999; }
}

See: http://jsfiddle.net/vd2Hx/

Tested in Chrome, Firefox, Safari, Opera, and IE.

John Kurlak
  • 6,594
  • 7
  • 43
  • 59