20

I want to hide a div based on the text inside. In the example below I want to hide the ones with "Handtekening" and the one with "Thuis". I prefer to do that with CSS. Is that possible?

The class names of the divs have to be the same...

<div class="test">
     Pakket
</div>
<div class="test">
     Handtekening
</div>
<div class="test">
     Thuis
</div>

If not possible with CSS, how can it be done with JavaScript?

Paolo Forgia
  • 6,572
  • 8
  • 46
  • 58
Jilco Tigchelaar
  • 2,065
  • 8
  • 31
  • 51

12 Answers12

13

Here's an easy vanilla Javascript solution:

const divs = document.getElementsByClassName('test');

for (let x = 0; x < divs.length; x++) {
    const div = divs[x];
    const content = div.textContent.trim();
  
    if (content == 'Handtekening' || content == 'Thuis') {
        div.style.display = 'none';
    }
}

Working JSFiddle here

Remember to include the script at the end of your HTML page (right before the </body> tag).

o01
  • 5,191
  • 10
  • 44
  • 85
  • Works! To make It perfect, is it also possible to use something like contains? So if the tekst inside the div is "Handtekening test" that I select on contains Handtekening? – Jilco Tigchelaar Oct 17 '17 at 13:24
  • Indeed, just use indexOf instead. Here's an updated JSFiddle: https://jsfiddle.net/1v5qed2n/2/ – o01 Oct 17 '17 at 13:28
  • Yes, using `indexOf()` is safer here, for checking the content. – cнŝdk Oct 17 '17 at 13:29
  • 2
    You should not use `.innerHTML` in this instance. `.textContent` would be more appropriate, or `.innerText` if you need compatibility with – Makyen Oct 17 '17 at 18:36
  • 1
    Ouch! This may work for OP's specific example, but generally it will not. Imagine if the text I'm looking for is `img` and a div doesn't contain this text but contains an image. – Aleks G Oct 17 '17 at 19:57
12

If you have control over the HTML output and have no problems with the text document getting twice as big, you can duplicate the content of each of those divs. Otherwise JavaScript is the way to go. Here is the CSS solution:

<div class="test" content="Pakket">
Pakket
</div>
<div class="test" content="Handtekening">
Handtekening
</div>
<div class="test" content="Thuis">
Thuis
</div>

Then use the selector for an attribute containing a string:

div[content~=Thuis] { display:none; }

The one above will match when "Thuis" is contained in the text as a separate word. If you want to match any occurrence of the string, you should use:

div[content*=and] { display:none; }
DreamWave
  • 1,934
  • 3
  • 28
  • 59
7

No, it won't be possible with pure CSS. You need to use JavaScript to do it.

This is code you can use for that:

var divs = document.querySelectorAll(".test");
Array.from(divs).forEach(function(div) {
  if (div.textContent.indexOf("Handtekening") >= 0 || div.textContent.indexOf("Thuis") >= 0) {
    div.style.display = "none";
  }
});

var divs = document.querySelectorAll(".test");
Array.from(divs).forEach(function(div) {
  if (div.textContent.indexOf("Handtekening") >= 0 || div.textContent.indexOf("Thuis") >= 0) {
    div.style.display = "none";
  }
});
<div class="test">
  Pakket
</div>
<div class="test">
  Handtekening
</div>
<div class="test">
  Thuis
</div>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
cнŝdk
  • 31,391
  • 7
  • 56
  • 78
5

Here's one more solution:

Array.from( document.querySelectorAll('div.test') )
  .filter( node => /\b(Handtekening|Thuis)\b/i.test(node.textContent) )
  .forEach( node => node.style.display = 'none' );
<div class="test">
     Pakket
</div>
<div class="test">
     HANDTEKENING
</div>
<div class="test">
     Test thuis blah blah
</div>

The main difference from chsdk's solution is that I'm using a single regexp test instead of multiple .indexOf() calls. IMO this is cleaner, more flexible and possibly more efficient as well.


The \b anchors in the regexp match word boundaries, so that e.g. "Thuis test" is matched but "Thuistest" is not. I suspect this is what the OP wants, but if not, the \b anchors can easily be removed and/or replaced with something else. For example, the regexp:

/^\s*(Handtekening|Thuis)\b/i

would match only if the words "Handtekening" or "Thuis" occur at the beginning of the content (possibly after some whitespace). Replacing the second \b with \s*$ would also require there to be nothing (except possibly whitespace) after the matched word.

The i flag at the end of the regexp literal makes the matching case-insensitive. If not desired, the i can simply be removed. I wanted to include it for illustrative purposes, though.


Ps. Some older browsers (such as, notably, Internet Explorer) may not support the ES6 arrow functions and the Array.from() method used in the code above. If compatibility with such old browsers is desired, here's an alternative implementation free from any such newfangled stuff:

var nodes = document.querySelectorAll('div.test');
for (var i = 0; i < nodes.length; i++) {
    if ( /\b(Handtekening|Thuis)\b/i.test(nodes[i].textContent) ) {
        nodes[i].style.display = 'none';
    }
}
<div class="test">
     Pakket
</div>
<div class="test">
     HANDTEKENING
</div>
<div class="test">
     Test thuis blah blah
</div>

AFAICT, this should be compatible with IE down to version 9, and of course with all modern browsers as well.

Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
3

You could do the easy thing of hiding the elements with a second class.

So let's say we'll add the class="hidden".

See the example below:

.test {
    color: blue;
}

.hidden {
    display: none;
    /* or visibility: hidden; */
}
<div class="test">
    Pakket
</div>
<div class="test hidden">
    Handtekening
</div>
<div class="test hidden">
    Thuis
</div>

By adding the second class we're able to make a selection of which <div> element you'd like to show and which not.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Deathstorm
  • 818
  • 11
  • 36
2

To select elements based on text you can use js and check if text is equal to ones you want to hide. If it is you can set display property to none to hide that element.

[...document.querySelectorAll('.test')].forEach(function(e) {
  if (['Handtekening', 'Thuis'].includes(e.textContent.trim())) {
    e.style.display = 'none'
  }
})
<div class="test">
  Pakket
</div>
<div class="test">
  Handtekening
</div>
<div class="test">
  Thuis
</div>
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176
1
  • With CSS 3: no
  • With JavaScript: yes
  • With XPath: yes (something like //div[contains(text(),'Handtekening')]/.)

You can test your XPath here.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Chtioui Malek
  • 11,197
  • 1
  • 72
  • 69
1

You can do it just like this,

let filteredOut = ['Handtekening', 'Thuis'];

Array.from(document.querySelectorAll(".test")).forEach((elm) => {
 if(filteredOut.includes(elm.textContent.trim())) elm.style.display = "none";
});

DEMO

  • Collect the values that are needs to be filtered out in a separate array.
  • Iterate over all the elements and check its value presents in the filter array.
  • If it exists, just hide it.

Side Note: You can use a class to add to the caught elements instead of inserting inline styles.

Rajaprabhu Aravindasamy
  • 66,513
  • 17
  • 101
  • 130
1

You can do it with JavaScript:

var elements = document.getElementsByClassName('test');

for(var i = 0; i<elements.length; i++){

 if(elements[i].innerText==='Handtekening' || elements[i].innerText==='Thuis'){
  elements[i].style.display = 'none';
 }

}
<div class="test">
Pakket
</div>
<div class="test">
Handtekening
</div>
<div class="test">
Thuis
</div>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Renzo Calla
  • 7,486
  • 2
  • 22
  • 37
1

Here's pure JavaScript solution:

// Define your variables
var objectsToCheck = document.getElementsByClassName("test");
var hideText = "Pakket";

// Loop through your div objects
[].forEach.call(objectsToCheck, function (o) {

  // Check if text appears in div under class "test"
  if(o.innerText.toLowerCase() == hideText.toLowerCase()){
      o.style.display = "none";
  }
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Yerlan
  • 21
  • 3
0

You also have jQuery that makes this easy if you already use this library: contains(text).

text: A string of text to look for. It's case sensitive.

The matching text can appear directly within the selected element, in any of that element's descendants, or a combination thereof. As with attribute value selectors, text inside the parentheses of :contains() can be written as a bare word or surrounded by quotation marks. The text must have matching case to be selected.

$( ".test:contains('Thuis'),.test:contains('Handtekening')" ).css( "display", "none" );

https://codepen.io/gc-nomade/pen/zEMbLz

Community
  • 1
  • 1
G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
0

You can use querySelector to fetch elements and use element.classList.toggle to add/remove a class that will hide the value.

document.querySelector('#btn').addEventListener('click', function(){
  var text = document.querySelector('#txt').value.trim();
  
  var list = document.querySelectorAll('.test');
  for(var i = 0; i< list.length; i++) {
    list[i].classList.toggle('hide', list[i].textContent.trim() === text);
  }
})
.hide {
  display: none;
}
<div class="test">
Pakket
</div>
<div class="test">
Handtekening
</div>
<div class="test">
Thuis
</div>

<input type='text' id='txt' />
<button id='btn'>Hide Div</button>
Rajesh
  • 24,354
  • 5
  • 48
  • 79