admin管理员组

文章数量:1301568

I'm trying to adapt a function from w3schools to toggle the visibility of a div by switching between display:none and display:block.

The display property of said div is defined via css. If display is initially set to 'block', everything works fine, but not if it's initially set to 'none'.

function myFunction() {
    var x = document.getElementById("myDIV");
    if (x.style.display === "none") {
        x.style.display = "block";
    } else {
        x.style.display = "none";
    }
}
#myDIV {
    width: 100%;
    padding: 50px 0;
    text-align: center;
    background-color: lightblue;
    margin-top: 20px;
    display : block;
}
<p>Click the button to toggle between hiding and showing the DIV element:</p>

<button onclick="myFunction()">Click</button>

<div id="myDIV">
  This is my DIV element.
</div>

I'm trying to adapt a function from w3schools. to toggle the visibility of a div by switching between display:none and display:block.

The display property of said div is defined via css. If display is initially set to 'block', everything works fine, but not if it's initially set to 'none'.

function myFunction() {
    var x = document.getElementById("myDIV");
    if (x.style.display === "none") {
        x.style.display = "block";
    } else {
        x.style.display = "none";
    }
}
#myDIV {
    width: 100%;
    padding: 50px 0;
    text-align: center;
    background-color: lightblue;
    margin-top: 20px;
    display : block;
}
<p>Click the button to toggle between hiding and showing the DIV element:</p>

<button onclick="myFunction()">Click</button>

<div id="myDIV">
  This is my DIV element.
</div>

Please see this codepen example. If you change the css to display: none; you need to click the button twice(!) before the div toggles to block. Why does the script not recognize the initial 'none'?

Share edited Oct 21, 2017 at 21:13 cl10k asked Oct 21, 2017 at 21:08 cl10kcl10k 9511 gold badge7 silver badges18 bronze badges 0
Add a ment  | 

5 Answers 5

Reset to default 8

The problem is that you are initially getting the display property value via the style property of the object. But, that property only returns "inline" styles applied to an element, like this:

<div style="display:none;">something</div>

Since you are setting display:none via a separate "internal style" and not an inline style, the initial value returned from x.style.display is an empty string, so then your code execution falls into the else branch of your if statement and a new inline style is then set for the element. This is why it works on the second click - - the first click actually creates an inline style where none existed before, and therefore the second click works.

You should be using window.getComputedStyle(x).display; to get the value because .getComputedStyle() gets a property value regardless of where or how it was set upon the element.

function myFunction() {
    var x = document.getElementById("myDIV");
    var displayValue = window.getComputedStyle(x).display;
    if (displayValue === "none") {
        x.style.display = "block";
    } else {
        x.style.display = "none";
    }
}
#myDIV {
    display:none;
    width: 100%;
    padding: 50px 0;
    text-align: center;
    background-color: lightblue;
    margin-top: 20px;
}
<p>Click the button to toggle between hiding and showing the DIV element:</p>

<button onclick="myFunction()">Click</button>

<div id="myDIV">
  This is my DIV element.
</div>

Having said this, working with inline styles is generally considered a last resort because of how granular the code must get, how they lead to duplication of code, how non-scalable the code bees and how difficult it can be to override inline styles. It is much simpler to set up CSS classes ahead of time and then apply or remove those classes to elements as needed. DOM elements support a .classList property that provides easy ways to add, remove and toggle classes (toggle is what you want here). This approach makes the actual function code much simpler:

function myFunction() {
    document.getElementById("myDIV").classList.toggle("hidden");
}
#myDIV {
    width: 100%;
    padding: 50px 0;
    text-align: center;
    background-color: lightblue;
    margin-top: 20px;
}

/* This class will be added, removed or toggled as needed.
   It is kept separate from the element's style so that only
   this property can be toggled as needed without affecting 
   the other styling of the element. Also, it can be used
   for any other elements (as needed) that may need to be 
   hidden at some point. */
.hidden { display:none; }
<p>Click the button to toggle between hiding and showing the DIV element:</p>
<button onclick="myFunction()">Click</button>

<!-- Notice that the element has the class applied to it from the start 
     to ensure that the element is hidden from the start.                -->
<div id="myDIV" class="hidden">This is my DIV element.</div>

function myFunction() {
    var x = document.getElementById("myDIV");
    if (x.style.display === "") {
        x.style.display = "block";
    } else {
        x.style.display = "";
    }
}
#myDIV {
    display: none;
    width: 100%;
    padding: 50px 0;
    text-align: center;
    background-color: lightblue;
    margin-top: 20px;
}
<p>Click the button to toggle between hiding and showing the DIV element:</p>

<button onclick="myFunction()">Click</button>

<div id="myDIV">
  This is my DIV element.
</div>

an element is like most things in JavaScript an object that has properties. One of them is style. Styles set via a stylesheet don't get set as inline styles. So when you initially set display: none through a stylesheet, x.style.display will return undefined since no style property has been set on the element itself. It's mon practice to avoid setting inline styles.

Try another approach using classlist.

function myFunction() {
    var x = document.getElementById("myDIV");
    if (x.classList.contains("hide")) //check if element has hide as classname
    {
       x.classList.remove("hide");
    } else {
        x.classList.add("hide");
    }
}
#myDIV {
    width: 100%;
    padding: 50px 0;
    text-align: center;
    background-color: lightblue;
    margin-top: 20px;
    display : block;
}

#myDIV.hide{
  display: none;
}
<p>Click the button to toggle between hiding and showing the DIV element:</p>

<button onclick="myFunction()">Click</button>

<div id="myDIV" class="hide">
  This is my DIV element.
</div>

Note that it is different the display: none in the CSS file to setting the x.style.display = "none". In one case you are affecting a CSS rule, in other case you are changing the inline style of the element. So, even if in the CSS you have set display: "none", x.style.display will be undefined the first time you check it:

if (x.style.display === "none") {  <<< jumps to the else!

There are multiple options, but you could be to check the puted style instead:

let display = getComputedStyle(x).getPropertyValue("display");
if (display === "none") {

I hope it helps!

If your users are using relatively new browsers you can use the classList API to greatly shorten your code and in browsers that don't support it you can just poly-fill it.

JavaScript:

function myFunction() {
    var el = document.querySelector("#myDiv");

    el.classList.toggle("show");
};

CSS:

#myDIV {
    width: 100%;
    padding: 50px 0;
    text-align: center;
    background-color: lightblue;
    margin-top: 20px;
    display : none;
}

#myDIV.show{
  display: block;
}

本文标签: javascriptCSS trouble with displaynone not being recognizedStack Overflow