skip to Main Content

In the example, I have to click twice to see Foo content, but only once to see Bar content. The only difference is that Foo content has a internal style and Bar has inline style.

<html>

<head>
  <style>
    .content {
      display: none;
    }
  </style>

  <script>
    function showHide(element) {
      sibling = element.nextElementSibling;
      if (sibling.style.display == "none")
        sibling.style.display = "block"
      else sibling.style.display = "none";
    }
  </script>
</head>

<body>
  <h1 onclick="showHide(this)">Foo</h1>
  <div class="content">
    Foo Content
  </div>

  <h1 onclick="showHide(this)">Bar</h1>
  <div style="display: none;">
    Bar Content
  </div>
</body>

</html>

You can see this code in jsfiddle here

I’d like to use internal css or external css but having the same behaviour as I get in inline css, is this possible?
I guess this is a basic topic, but I don’t know what concepts to use to going deeper.

2

Answers


  1. When you read sibling.style.display from JavaScript, you get the inline display style on that element. When there is no inline display style, you get "". Getting the computed style is something you can do, but the better general solution is not to set styles directly from JavaScript at all, and instead manipulate meaningful classes:

    function showHide(element) {
        const sibling = element.nextElementSibling;
        sibling.classList.toggle("content-hidden");
    }
    .content-hidden {
        display: none;
    }
    <h1 onclick="showHide(this)">Foo</h1>
    <div class="content-hidden">
        Foo Content
    </div>
    
    <h1 onclick="showHide(this)">Bar</h1>
    <div class="content-hidden">
        Bar Content
    </div>

    In this specific case, you might just be looking for <details>, though:

    .thing > summary {
      display: flex;
    }
    <details class="thing">
        <summary><h1>Foo</h1></summary>
        Foo Content
    </details>
    
    <details class="thing">
        <summary><h1>Bar</h1></summary>
        Bar Content
    </details>
    Login or Signup to reply.
  2. The issue is that sibling.style.display refers to the style attribute, not the computed style for the element. You’ll notice that if you click it again it works, because the first click sets the style to display: none so a subsequent click makes it visible.

    But you can solve this by using the element’s classList to toggle a class that makes it visible, as in this example.

    function showHide(element) {
      sibling = element.nextElementSibling;
      sibling.classList.toggle('visible')
    }
    .content {
      display: none;
    }
    
    .visible {
      display: block;
    }
    <h1 onclick="showHide(this)">Foo</h1>
    <div class="content">
      Foo Content
    </div>
    
    <h1 onclick="showHide(this)">Bar</h1>
    <div class="content">
      Bar Content
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search