Hide an element if the next one is empty
Asked Answered
R

9

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 ?

Randyranee answered 30/6, 2013 at 14:37 Comment(1)
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: dev.w3.org/csswg/selectors4/#profiles).Expulsive
O
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.

Oxazine answered 30/6, 2013 at 14:53 Comment(2)
Please, read the specifaction you linked to; specifically 2.1. Fast vs Complete Selector Profiles. Yes, the Selectors API has*/*may have a subject pseudo-class; but it won't be available (as currently written) in browser CSS.Expulsive
Thanks. I've altered the answer to reflect that. Had to read and re-read it a half dozen of times though.Oxazine
K
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

Kentonkentucky answered 30/6, 2013 at 14:42 Comment(5)
You might want to explain why you're using jQuery, when the tags are css and css3.Expulsive
One liner: $('h3.hideIfDivEmpty + div:empty').prev().hide();Lesko
@Lesko how would you do the same thing but trimming any whitespace [trim()] first?Cannibalize
@MichaelYaeger untested: $('h3.hideIfDivEmpty + div:empty').filter(function() { return $(this).text().trim() === '' }).prev().hide();Lesko
@Lesko unfortunately that didn't work. However, it seems the one-liner is becoming as long as the standard version which is as easy as tacking on .trim().Cannibalize
B
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

Brae answered 30/6, 2013 at 14:43 Comment(0)
W
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: "; }
Wittol answered 15/9, 2015 at 13:26 Comment(1)
This technique works - but alters the HTML significantly from OP'sEmbolism
E
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.

Expulsive answered 30/6, 2013 at 14:47 Comment(0)
H
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>
Hearten answered 30/6, 2013 at 15:31 Comment(1)
it's hacked indeed. i wonder why there is a selector for next sibling and not for previous thoughRandyranee
T
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>.

Torrens answered 30/6, 2013 at 17:42 Comment(1)
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.Randyranee
M
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>
Mainis answered 6/2, 2019 at 20:12 Comment(0)
C
0

Yes there is a possibility to look ahead with the has() selector. For you it would be:

h3#hideIfDivEmpty:has( + #divId:empty ) {
    display: none;
}
Chiou answered 14/8, 2024 at 9:49 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.