Problema de CSS con la pantalla: no se reconoce ninguno

3

Estoy tratando de adaptar una función de w3schools.com para alternar la visibilidad de un div cambiando entre display: none y display: block.

La propiedad de visualización de dicho div se define mediante css. Si la pantalla está configurada inicialmente como 'bloquear', todo funciona bien, pero no si está configurada inicialmente como 'ninguna'.

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>

Consulte este ejemplo de codepen . Si cambia el CSS para mostrar: ninguno; debe hacer clic en el botón dos veces (!) antes de que el div cambie a bloquear. ¿Por qué el guión no reconoce el "ninguno" inicial?

0
6

El problema es que inicialmente obtiene el displayvalor de la stylepropiedad a través de la propiedad del objeto. Pero esa propiedad solo devuelve estilos "en línea" aplicados a un elemento, como este:

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

Dado que está configurando a display:nonetravés de un "estilo interno" separado y no un estilo en línea, el valor inicial devuelto x.style.displayes una cadena vacía, por lo que la ejecución de su código cae en la elserama de su ifdeclaración y luego se establece un nuevo estilo en línea para el elemento . Esta es la razón por la que funciona en el segundo clic: el primer clic en realidad crea un estilo en línea donde no existía ninguno antes y, por lo tanto, el segundo clic funciona.

Debería usar window.getComputedStyle(x).display;para obtener el valor porque .getComputedStyle()obtiene un valor de propiedad independientemente de dónde o cómo se estableció en el elemento.

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>

Habiendo dicho esto, trabajar con estilos en línea generalmente se considera un último recurso debido a cuán granular debe ser el código, cómo conducen a la duplicación del código, cuán no escalable se vuelve el código y cuán difícil puede ser anular los estilos en línea. Es mucho más sencillo configurar las clases CSS con anticipación y luego aplicar o eliminar esas clases a los elementos según sea necesario. Los elementos DOM admiten una .classListpropiedad que proporciona formas fáciles de agregar, eliminar y alternar clases (alternar es lo que desea aquí). Este enfoque hace que el código de función real sea mucho más simple:

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>
1
  • 1
    Hola Scott, ¡gracias por tu excelente respuesta! ¡Fue de lo más útil y educativo!
    cl10k
    22 oct 2017 a las 0:30
0

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>
0

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 common practice to avoid setting inline styles.

Pruebe con otro enfoque 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>
2
  • 1
    "Sin embargo, las hojas de estilo (internas a través de <style> o un archivo CSS externo) usan un motor diferente para establecer las propiedades de estilo". No, no lo hacen. Es solo que los atributos del elemento DOM se convierten en propiedades de objeto JS, por lo que el styleatributo es accesible a través de la stylepropiedad, pero los estilos aplicados de otras formas no lo harán. Las tres formas de configurar estilos utilizan el mismo motor CSS. 21/10/2017 a las 21:35
  • ¡Cambiará esto!
    Mouser
    21/10/2017 a las 21:39
0

Tenga en cuenta que es diferente display: noneen el archivo CSS a configurar el x.style.display = "none". En un caso, está afectando una regla CSS, en otro caso, está cambiando el estilo en línea del elemento. Entonces, incluso si en el CSS que ha configurado display: "none", x.style.displayno estará definido la primera vez que lo verifique:

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

Hay varias opciones, pero podría verificar el estilo calculado en su lugar:

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

¡Espero que ayude!

0

Si sus usuarios están usando navegadores relativamente nuevos, puede usar la API classList para acortar en gran medida su código y en los navegadores que no lo admiten, puede simplemente rellenarlo.

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;
}