5

I have the following code :

<h3 class="hideIfDivEmpty">title</h3>
<div id="divId"></div>

I would like to hide the h3 element when the div is empty. I'm willing to change the html structure but the h3 has to be outside of the div because its content is dynamically changed.

Is there a way to do that in CSS ?

Lev Levitsky
  • 63,701
  • 20
  • 147
  • 175
MaD
  • 139
  • 1
  • 2
  • 9
  • 2
    No. CSS has no way of selecting a previous sibling of an element. At all. Despite the number of people that claim CSS 4 will allow it (despite clear statements to the contrary, ref: http://dev.w3.org/csswg/selectors4/#profiles). – David Thomas Jun 30 '13 at 14:42

8 Answers8

4

There is no syntax to select a parent element or any other non-child element from #divid. You can select #divid if it's empty, by #divid:empty, but there is no way you can select .hideIfDivIsEmpty in any browser by selecting that. According to this question there is such a thing in CSS4 (specs), but it is not supported in any browser as of now and according to the same specs, the selector is too slow to be implemented in browsers.

See the other answers for the javascript solution to this problem.

Community
  • 1
  • 1
Sumurai8
  • 20,333
  • 11
  • 66
  • 100
  • Please, *read* the specifaction you linked to; specifically [2.1. Fast vs Complete Selector Profiles](http://dev.w3.org/csswg/selectors4/#profiles). Yes, the Selectors API *has*/*may have* a `subject` pseudo-class; but it *won't* be available (as currently written) in browser CSS. – David Thomas Jul 01 '13 at 14:09
  • Thanks. I've altered the answer to reflect that. Had to read and re-read it a half dozen of times though. – Sumurai8 Jul 01 '13 at 14:54
1

I don't think that you can do it with CSS.

Use jQuery instead:

var divs = $(".hideIfDivEmpty");

divs.each(function () {
    var div = $(this);

    if (div.next().html() === "") {
        div.hide();
    }
});

JSFIDDLE

And like @Prinzhorn correctly said: there is a liner solution:

$('h3.hideIfDivEmpty + div:empty').prev().hide();

JSFIDDLE

Ionică Bizău
  • 109,027
  • 88
  • 289
  • 474
1

well wait you are going to get some very good answers here. but my solution would be make a css class then assign it to both the h3 and div tags then using jquery selectors get both of them using the css class. Now you will get an arry of tags if the the element at index 1's innertext = null or empty then the element at index 0 should hide. i hope this will help

khalid khan
  • 135
  • 1
  • 9
1

Add your label using the ::before css selector.

Hide your label for empty/null values using the :empty selector

(Both require IE9+)

HTML

<div class="label l_colour"></div>
<div class="label l_size"></div>
<div class="label l_shape"></div>

CSS

/* HIDE IF EMPTY*/
.label:empty { display: none; }

/* LABEL STYLES */
.label::before { font-weight:bold; }

/* LABEL VALUES */
.l_colour::before { content:"Colour: "; } 
.l_size::before { content: "Size: "; }
.l_shape::before { content: "Shape: "; }
Paul Sturm
  • 2,118
  • 1
  • 18
  • 23
Gigilamesh
  • 11
  • 2
0

This problem can only be solved client-side with JavaScript (or one of its libraries). With plain JavaScript, I'd suggest:

function hideIfNextEmpty(el) {
    var text = 'textContent' in document ? 'textContent' : 'innerText';
    if (el.nextElementSibling[text].replace(/\s/g,'').length === 0) {
        el.style.display = 'none';
    }
}

hideIfNextEmpty(document.querySelector('h3.hideIfDivEmpty'));

JS Fiddle demo.

David Thomas
  • 249,100
  • 51
  • 377
  • 410
0

A CSS-only version would not have very good browser support. It would involve putting the header tag after the content, followed by manipulating the positioning of the elements.

Here's a very hacked together CSS-only solution. IE 9+. You should do this using JavaScript instead as others have suggested.

http://jsfiddle.net/znLMe/

CSS

article p:empty + header {
    display: none;
}

article p:empty {
    margin: 0;
}

article p {
    float:left;
}

article header {
    position: absolute;
    top: 0;
}
article header h1 {
    margin: 0;
}

article > p:first-of-type:not(:empty) {
    padding-top: 1em;
}

article {
    position: relative;
}

/* include clearfix */

HTML

<article class="clearfix">
    <p></p>
    <header><h1>Hidden article</h1></header>
</article>

<article class="clearfix">
    <p>Cras mattis consectetur purus sit amet fermentum. Maecenas faucibus mollis interdum. Cras mattis consectetur purus sit amet fermentum. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Cras mattis consectetur purus sit amet fermentum. Nulla vitae elit libero, a pharetra augue.</p>
    <header><h1>Porta Malesuada</h1></header>
</article>
thgaskell
  • 12,772
  • 5
  • 32
  • 38
  • it's hacked indeed. i wonder why there is a selector for next sibling and not for previous though – MaD Jun 30 '13 at 16:58
0

How is the content of the <div> entered? Because a non-JS solution would simply involve entering classes (e.g. "is-hidden"). If you're manually entering content in the HTML, then you can add the classes yourself. If you're loading content dynamically through a template, then you should be able to write some simple logic that applies a class to the <h3> element based on the content to be entered into the <div>.

davidtheclark
  • 4,666
  • 6
  • 32
  • 42
  • yes that's what i'm going to do eventually. I was just wondering if there was a css only solution involving no additionnal javascript or server side processing. – MaD Jun 30 '13 at 20:23
0

I'm willing to change the html structure...

The answer is YES with this structure flexibility. Have the DIV precede the H3 element and add the following CSS rule:

// testing purposes only | see css and new html structure 
document.querySelector('button').addEventListener('click', function() {
  var el = document.querySelector('#divId');
  if(el.textContent.length > 0) {
    el.textContent = "";
  } else {
    el.textContent = "Hello world!";
  }
});
div#divId:empty + h3.hideIfDivEmpty {
  display: none;
}
<div id="divId">Hello world!</div>
<h3 class="hideIfDivEmpty">title</h3>

<!-- Button adds and removes text within div -->
<button>Toggle Text</button>
Sterling Beason
  • 622
  • 6
  • 12