Elimina el destello del contenido sin estilo

81

¿Cómo detengo el destello de contenido sin estilo (FOUC) en una página web?

Crítico de CMS
fuente
Esto sucede muchas veces si tenemos la etiqueta de enlace de las hojas de estilo al final de la página web.
RBT

Respuestas:

3

Lo que he hecho para evitar FOUC es:

  • Establezca la sección del cuerpo como: <body style="visibility: hidden;" onload="js_Load()">

  • Escribe una js_Load()función de JavaScript:document.body.style.visibility='visible';

Con este enfoque, el cuerpo de mi página web se mantiene oculto hasta que se cargan la página completa y los archivos CSS. Una vez que todo está cargado, el evento onload hace que el cuerpo sea visible. Por lo tanto, el navegador web permanece vacío hasta el momento en que todo aparece en la pantalla.

Es una solución simple pero hasta ahora está funcionando.

Álvaro Durán
fuente
60
No es bueno si un espectador no tiene habilitado javascript, porque entonces no verá nada.
Stefan
19
-1 por sugerir una solución que no mostrará NADA para los usuarios que no tienen javascript habilitado, o están en un lector de pantalla que no es compatible con javascript, o que están detrás de un firewall corporativo que bloquea javascript. Buscar en Google "eliminar flash de contenido no deseado" mostrará numerosos enfoques que no tienen este defecto. Por ejemplo, la respuesta de Stefan (un año después) es mucho más segura.
ToolmakerSteve
16
Realmente debería agregar <noscript><style>body { visibility: visible; }</style></noscript>al final para que el sitio funcione con JS deshabilitado también.
tomasz86
4
¿Los cortafuegos corporativos bloquean Javascript? Una razón para cambiar de empresa ...
unwichtich
3
La respuesta de Jeff a continuación es la respuesta correcta en mi opinión. No depende de javascript y es más accesible.
braindigitalis
83

El problema de usar un estilo CSS para ocultar inicialmente algunos elementos de la página, y luego usar javascript para cambiar el estilo de nuevo a visible después de cargar la página, es que las personas que no tienen Javascript habilitado nunca podrán ver esos elementos. Entonces es una solución que no se degrada con gracia.

Por lo tanto, una mejor manera es usar javascript tanto para ocultar inicialmente como para volver a mostrar esos elementos después de cargar la página. Usando jQuery, podríamos tener la tentación de hacer algo como esto:

$(document).ready(function() {
    $('body').hide();
    $(window).on('load', function() {
        $('body').show();
    });
});

Sin embargo, si su página es muy grande con muchos elementos, entonces este código no se aplicará lo suficientemente pronto (el cuerpo del documento no estará listo lo suficientemente pronto) y es posible que todavía vea un FOUC. Sin embargo, hay un elemento que PODEMOS ocultar tan pronto como se encuentre el script en el encabezado, incluso antes de que el documento esté listo: la etiqueta HTML. Entonces podríamos hacer algo como esto:

<html>
  <head>
  <!-- Other stuff like title and meta tags go here -->
  <style type="text/css">
    .hidden {display:none;}
  </style>
  <script type="text/javascript" src="/scripts/jquery.js"></script>
  <script type="text/javascript">
    $('html').addClass('hidden');
    $(document).ready(function() {    // EDIT: From Adam Zerner's comment below: Rather use load: $(window).on('load', function () {...});
      $('html').show();  // EDIT: Can also use $('html').removeClass('hidden'); 
     });  
   </script>
   </head>
   <body>
   <!-- Body Content -->
   </body>
</html>

Tenga en cuenta que el método jQuery addClass () se llama * fuera * del método .ready () (o mejor, .on ('load')).

Stefan
fuente
4
A mí me parece más limpio para reemplazar $('html').show()'con $('html').removeClass('hidden');. Esto deja más claro que la función listo deshace el archivo addClass.
ToolmakerSteve
6
ACTUALIZACIÓN: Acabo de probar este enfoque. La versión actual de jQuery REQUIERE que esto se haga usando removeClass(como sugiero) en lugar de show(como en la respuesta original); de lo contrario, el html NUNCA se mostrará. Creo que show () de jQuery ahora busca y restaura explícitamente cualquier estado de visualización del estilo css, para evitar interferir con el estilo. Por lo tanto, es necesario eliminar la clase 'oculta'.
ToolmakerSteve
1
Funciona perfectamente. Optó por la opción removeClass en lugar de show ()
FurryWombat
3
¿Qué tal una solución única de CSS en la que tiene <style>html { display: none; }</style>en el <head>y luego sus estilos reales justo antes </body>?
Adam Zerner
2
¿No deberíamos buscar el evento de carga en lugar de estar listo? Con la carga, sabemos que el CSS estará listo. Con listo, no sabemos que el CSS estará listo.
Adam Zerner
31

Una solución solo de CSS:

<html>
  <head>
    <style>
      html {
        display: none;
      }
    </style>
    ...
  </head>
  <body>
    ...
    <link rel="stylesheet" href="app.css"> <!-- should set html { display: block; } -->
  </body>
</html>

A medida que el navegador analiza el archivo HTML:

  • Lo primero que hará es esconderse <html>.
  • Lo último que hará es cargar los estilos y luego mostrar todo el contenido con el estilo aplicado.

La ventaja de esto sobre una solución que usa JavaScript es que funcionará para los usuarios incluso si tienen JavaScript desactivado.

Nota: se le permite poner <link>dentro de <body>. Sin embargo, lo veo como una desventaja, porque viola la práctica común. Sería bueno si hubiera un deferatributo para <link>como hay para <script>, porque eso nos permitiría ponerlo en el <head>y aún así lograr nuestro objetivo.

Adam Zerner
fuente
5
Es útil saber que display: nonetambién ocultará la imagen de fondo o el color. Dado que mi sitio web tiene un tema oscuro, parpadeará en blanco. Usar visibility: hiddenfue mejor para mi caso.
KamilDev
1
Esta solución funcionará incluso si la referencia a la hoja de estilo está en <head>lugar de <body>. (Aunque supongo que si tuviera una página muy larga, el navegador podría comenzar a mostrar la página antes de que se haya cargado el final de la página. Sin embargo, ese es mi comportamiento preferido ya que mi sitio carga tablas grandes desde una base de datos). ¡Aprobado por una solución simple que no requiere JavaScript!
Matt
28

Este es el que me ha funcionado y no requiere javascript y funciona muy bien para páginas con muchos elementos y mucho css:

Primero, agregue una <STYLE>configuración dedicada para la <HTML>etiqueta con visibilidad 'oculta' y opacidad como '0' en la parte superior de su HTML, por ejemplo, al principio del <HEAD>elemento, por ejemplo, en la parte superior de su HTML agregar :

<!doctype html>
<html>
<head>
    <style>html{visibility: hidden;opacity:0;}</style>

Luego, al final de su último archivo de hoja de estilo .css , configure los estilos de visibilidad y opacidad en 'visible' y '1', respectivamente:

html {
    visibility: visible;
    opacity: 1;
}

Si ya tiene un bloque de estilo existente para la etiqueta 'html', mueva todo el estilo 'html' al final del último archivo .css y agregue las etiquetas 'visibilidad' y 'opacidad' como se describe arriba.

https://gist.github.com/electrotype/7960ddcc44bc4aea07a35603d1c41cb0

Jeff
fuente
6
Esta realmente debería ser la respuesta correcta aceptada. No mostrar ninguna página si JS está deshabilitado o si hay un error de JS es una mala idea y esto es mucho más accesible.
braindigitalis
@Jeff, ¡muchas gracias por esta solución! ¡Resolvió mi problema!
yathrakaaran
1
Esto tampoco interfiere con los navegadores que tienen CSS deshabilitado (por ejemplo, aquellos con acceso a Internet de baja velocidad o tienen discapacidades pueden optar por deshabilitar imágenes, Javascript y CSS). Opera fue probablemente el ejemplo más famoso de un navegador que tenía, en un momento, un botón en la barra de herramientas principal para desactivar CSS. La desventaja de este enfoque es que si el archivo CSS no se carga, la página estará en blanco. Por ejemplo, nombrar su archivo CSS "ads.css" activará complementos de bloqueador de anuncios y el archivo no se cargará, dejando la página completamente en blanco. (Por supuesto, eso podría ser intencional ...)
CubicleSoft
Esta es la técnica que empleo y que más me gusta; sin embargo, encuentro que necesito usar html{display:none;}en heady html{display:block;}en la hoja de estilo para conquistar completamente FOUC con navegadores basados ​​en Chromium. (No he tenido problemas con un fondo oscuro en el body.)
dotism
Prácticamente no hay diferencia entre esta solución y la solución de Adam Zerner, hace más de un año.
Stefan
17

Una solución que no depende de jQuery, que funcionará en todos los navegadores actuales y no hará nada en los navegadores antiguos, incluye lo siguiente en su etiqueta principal:

<head>
    ...

    <style type="text/css">
        .fouc-fix { display:none; }
    </style>
    <script type="text/javascript">
        try {
            var elm=document.getElementsByTagName("html")[0];
            var old=elm.class || "";
            elm.class=old+" fouc-fix";
            document.addEventListener("DOMContentLoaded",function(event) {
                elm.class=old;
                });
            }
        catch(thr) {
            }
    </script>
</head>

Gracias a @justastudent, intenté configurarlo elm.style.display="none";y parece funcionar como se desea, al menos en el Firefox Quantum actual. Así que aquí hay una solución más compacta, siendo, hasta ahora, la cosa más simple que he encontrado que funciona.

<script type="text/javascript">
    var elm=document.getElementsByTagName("html")[0];
    elm.style.display="none";
    document.addEventListener("DOMContentLoaded",function(event) { elm.style.display="block"; });
</script>
Lawrence Dol
fuente
el código mencionado no funcionó para mí, aquí está mi versión: intente {var html = document.getElementsByTagName ("html") [0]; document.addEventListener ("DOMContentLoaded", función (evento) {html.className = '';}); html.className = 'fouc'; } catch (err) {}
Manfred Wuits
Me gusta este enfoque, pero me gustaría sugerir el uso de la classListAPI.
Solo un estudiante
2
De hecho, ¿por qué usar el CSS separado en primer lugar? ¿Por qué no hacer elm.style.display = 'none';y luego deshacer eso elm.style.removeProperty('display');?
Solo un estudiante
@Justastudent: Porque eso mostraría una página en blanco en caso de que Javascript esté deshabilitado.
Lawrence Dol
1
@Justastudent: Gracias. Lo intenté y funciona, al menos en los navegadores actuales. Respuesta aumentada.
Lawrence Dol
11

Otra solución rápida que también funciona en Firefox Quantum es una <script>etiqueta vacía en <head>. Sin embargo, esto penaliza sus conocimientos sobre la velocidad de la página y el tiempo de carga general.

Tuve un 100% de éxito con él. Creo que también es la razón principal por la que las soluciones anteriores con otros JS están en proceso.

<script type="text/javascript">

</script>
Paul Crema
fuente
1
Súper interesante, incluso si es totalmente fiable
hombrecillo diminuto
4

Nadie ha hablado de CSS @import

Ese fue el problema para mí, estaba cargando dos hojas de estilo adicionales directamente en mi archivo css con @import

Solución simple: reemplace todos los @importenlaces con<link />

danidee
fuente
Esto me pasó a mí. Espero que en el futuro @importsea ​​sincrónico.
D. Pardal
1

Se me ocurrió una forma que no requiere ningún cambio de código real, ¡woohoo! Mi problema estaba relacionado con la importación de varios archivos css DESPUÉS de algunos archivos javascript.

Para resolver el problema, simplemente moví mis enlaces CSS para que estuvieran por encima de mis importaciones de JavaScript. Esto permitió que todo mi CSS se importara y estuviera listo para funcionar lo antes posible, de modo que cuando el HTML aparezca en la pantalla, incluso si el JS no está listo, la página tendrá el formato adecuado.

Jake Boomgaarden
fuente
1

Aquí está mi código .. espero que resuelva su problema

set <body style="opacity:0;">

<script>
    $(document).ready(function() {
        $("body").css('opacity', 1);
    });
</script>
Coding_snakeZ
fuente
Sorprendentemente, entre docenas de fragmentos que no funcionan para detener FOUC, este realmente funciona para mí. Tenga en cuenta que falta un final "en el estilo de la carrocería, debería ser<body style="opacity:0;">
abulka
0

La mejor solución que encontré hasta ahora es así:

  1. Agregue todos los estilos de su encabezado a un <style/> etiqueta en<head/>

  2. en la parte superior de la etiqueta de estilo agregar .not-visible-first{visibility: hidden}+ otro estilo de encabezado

  3. Agregue css a través de JS al final del cuerpo

    document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeend","<link rel=\"stylesheet\" href=\"/css/main.min.css?v=1.2.4338\" />");

  4. Y recuerda agregar .not-visible-first{visibility: visible} al final demain.min.css

Esta opción creará una mejor experiencia de usuario

Nagibaba
fuente
0

Podrías probar esto con vainilla

function js_method(){
//todos
var elementDiv = document.getElementById("main");
elementDiv.style.display ="block";
}
<body onload="js_method()" id="main" style="display:none">
//todos
<h2>Hello</h2>
</body>

Nazehs
fuente
0

La forma más sencilla que conozco es ocultar la etiqueta html y luego, en la parte inferior de su archivo javascript, desvanecer la etiqueta html.

HTML

<html style="display:none;">
    ...
</html>

Javascript

/*
 * FOUC Fix - Flash of Unstyled Content
 * By default, the <html> tag is hidden to prevent the flash of unstyled content.
 * This simple fadeIn() function will allow the page to gracefully fade in once 
 * all assets are loaded. This line of code must remain at the bottom of the js 
 * assets.
 */

$( 'html' ).fadeIn();

Fuente: https://gist.github.com/marchershey/139db0e8fd6f03a83578698409d333ce

Bagazo
fuente
1
Tenga en cuenta que fadeIn()es un método jQuery, no JavaScript nativo.
BadHorsie