4

If you want to select nodes without any children you might think about using :empty. Meanwhile the behaviour of :empty is very annoying as any whitespace will make that rule not apply. :blank selector comes here as a saviour but no browser has implemented it yet.

Do you know of any trick to select elements with no other elements inside?

Just to stimulate your imagination: what about something like .parent:not(:scope > *)

Vandervals
  • 5,774
  • 6
  • 48
  • 94
  • 1
    It is difficult to select unless CSS parent selector is introduced which is also a CSS4 selector. – m4n0 Oct 02 '15 at 08:24

3 Answers3

3

Selectors don't match text nodes, so there is no way to emulate either :blank, or :empty using a selector.

Taken literally, .parent:not(:scope > *) represents any .parent element that is not a child of the :scope element, whatever that scoping root may be. If the selector is not scoped, then it is equivalent to .parent:not(:root > *), or if it appears in a scoped stylesheet, generally it means any such element that is not a sibling of the style element representing this scoped stylesheet.

I suspect you mean something like .parent:not(:has(> *)), which will match .parent elements that don't have element children, but it doesn't take into account their text contents, again for the same reason I mentioned.

The good news is, while you still have to wait for vendors to get around to implementing this new feature, instead of implementing it in a separate :blank pseudo they're considering modifying the functionality of :empty instead, provided it doesn't break too many sites. See this answer.

Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
0

As BoltClock said there is no way to achieve this with css only for now - it would have been possible with the :contains() selector though it was given up from the CSS3 specification.

I know this is not what you was looking for, but here is a jQuery solution that I sometimes use:

(function($){
    $.isBlank = function(html, obj){
        return $.trim(html) === "" || obj.length == 0;
    };

    $('li').each(function() {
        if($.isBlank(
            $(this).html(), 
            $(this).contents().filter(function() {
                return (this.nodeType !== Node.COMMENT_NODE);
            })
        )) {
            $(this).addClass('empty');
        }
    });
})(jQuery);

See the jsfiddle demo. It target any node that have only spaces in it, or comments, but ignore elements with childs. Probably not perfect but it worked fairly for me so far.

vard
  • 4,057
  • 2
  • 26
  • 46
0

I have changed to become more general and accept whitespace with comment.

  $('*').contents().each(function() {
    if(this.nodeType === Node.COMMENT_NODE) {
      $(this).remove();
    }
  });

  (function($){
    $.isBlank = function(html, obj){
      return $.trim(html) === "" || obj.length == 0;
    };

    $('*').each(function() {
      if($.isBlank(
        $(this).html(), 
        $(this).contents().filter(function() {
          return (this.nodeType !== Node.COMMENT_NODE);
        })
      )) {
           $(this).addClass('blank');
         }
    });
  })(jQuery);
Carlos Machado
  • 139
  • 1
  • 3