Устранение вспышки нестилизованного контента

81

Как остановить мигание нестилизованного содержимого (FOUC) на веб-странице?

CMS Critic
источник
Это происходит много раз, если в нижней части веб-страницы есть ссылка на таблицу стилей.
RBT

Ответы:

3

Что я сделал, чтобы избежать FOUC:

  • Установите раздел тела как: <body style="visibility: hidden;" onload="js_Load()">

  • Напишите функцию js_Load()JavaScript:document.body.style.visibility='visible';

При таком подходе тело моей веб-страницы остается скрытым до тех пор, пока не будет загружена полная страница и файлы CSS. Как только все загружено, событие onload делает тело видимым. Итак, веб-браузер остается пустым до тех пор, пока все не появится на экране.

Это простое решение, но пока оно работает.

Альваро Дуран
источник
60
Плохо, если у зрителя не включен javascript, потому что тогда они ничего не увидят.
Стефан
19
-1 за предложение решения, которое НИЧЕГО не покажет для пользователей, у которых не включен javascript, или которые используют программу чтения с экрана, которая не поддерживает javascript, или которые находятся за корпоративным брандмауэром, который блокирует javascript. Поиск в Google «Устранение нежелательного содержимого» покажет множество подходов, в которых нет этого недостатка. Например, ответ Стефана (год спустя) намного безопаснее.
ToolmakerSteve
16
Вам действительно стоит добавить <noscript><style>body { visibility: visible; }</style></noscript>в конце, чтобы сайт работал и с отключенным JS.
tomasz86
4
Корпоративные брандмауэры блокируют Javascript? Причина для смены компании ...
нет
3
На мой взгляд, ответ Джеффа, приведенный ниже, является правильным. Он не полагается на javascript и более доступен.
braindigitalis
83

Проблема с использованием стиля css для первоначального скрытия некоторых элементов страницы и последующим использованием javascript для изменения стиля обратно на видимый после загрузки страницы заключается в том, что люди, у которых не включен javascript, никогда не увидят эти элементы. Так что это решение, которое не ухудшается изящно.

Поэтому лучший способ - использовать javascript как для первоначального скрытия, так и для повторного отображения этих элементов после загрузки страницы. Используя jQuery, у нас может возникнуть соблазн сделать что-то вроде этого:

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

Однако, если ваша страница очень большая с большим количеством элементов, этот код не будет применен достаточно скоро (тело документа не будет готово достаточно скоро), и вы все равно можете увидеть FOUC. Однако есть один элемент, который мы МОЖЕМ скрыть, как только сценарий встречается в заголовке, даже до того, как документ будет готов: тег HTML. Итак, мы могли бы сделать что-то вроде этого:

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

Обратите внимание, что метод jQuery addClass () вызывается * вне * метода .ready () (или, лучше, .on ('load')).

Стефан
источник
4
Мне кажется чище заменить $('html').show()'на $('html').removeClass('hidden');. Это проясняет, что функция готовности отменяет работу addClass.
ToolmakerSteve
6
ОБНОВЛЕНИЕ: только что протестировал этот подход. Текущая версия jQuery ТРЕБУЕТ, чтобы это было сделано с использованием removeClass(как я предлагаю), а не show(как в исходном ответе) - в противном случае html НИКОГДА не будет отображаться. Я считаю, что jQuery show () теперь явно ищет и восстанавливает любое состояние отображения из стилей CSS, чтобы не мешать стилю. Следовательно, необходимо фактически удалить «скрытый» класс.
ToolmakerSteve
1
Прекрасно работает. Выбрал опцию removeClass вместо show ()
FurryWombat
3
Как насчет CSS только решения , где у вас есть <style>html { display: none; }</style>в <head>, и тогда ваши реальные стили прямо перед </body>?
Адам Зернер
2
Разве мы не должны искать событие загрузки, а не готово? После загрузки мы знаем, что CSS будет готов. Готово, мы не знаем, что CSS будет готов.
Адам Зернер
31

Решение только для CSS:

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

Когда браузер анализирует HTML-файл:

  • Первое, что он сделает, это спрячется <html>.
  • Последнее, что он сделает, это загрузит стили, а затем отобразит весь контент с примененным стилем.

Преимущество этого решения по сравнению с решением, использующим JavaScript, заключается в том, что оно будет работать для пользователей, даже если у них отключен JavaScript.

Примечание: вы позволили положить <link>внутри <body>. Я считаю это недостатком, потому что это нарушает общепринятую практику. Было бы неплохо, если бы был deferатрибут <link>как есть для <script>, потому что это позволило бы нам поместить его в <head>и при этом достичь нашей цели.

Адам Зернер
источник
5
Полезно знать, что display: noneэто также скроет фоновое изображение или цвет. Поскольку у моего веб-сайта темная тема, он будет мигать белым. В visibility: hiddenмоем случае использование было лучше.
KamilDev
1
Это решение будет работать, даже если ссылка на таблицу стилей находится <head>вместо <body>. (Хотя я полагаю, что если бы у вас была действительно длинная страница, браузер мог бы начать отображать страницу до того, как был загружен конец страницы. Однако на самом деле это мое предпочтительное поведение, поскольку мой сайт загружает большие таблицы из базы данных). Поднимите палец вверх за простое решение, не требующее JavaScript!
Мэтт
28

Это тот, который сработал для меня и не требует javascript, и он отлично работает для страниц с множеством элементов и большим количеством css:

Сначала добавьте специальный <STYLE>параметр для <HTML>тега с видимостью 'hidden' и непрозрачностью как '0' в верхней части вашего HTML, например, в начале <HEAD>элемента, например, в верхней части вашего HTML добавьте :

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

Затем в конце вашего последнего файла таблицы стилей .css установите для стилей видимости и непрозрачности значения «visible» и «1» соответственно:

html {
    visibility: visible;
    opacity: 1;
}

Если у вас уже есть существующий блок стиля для тега «html», переместите весь стиль «html» в конец последнего файла .css и добавьте теги «видимость» и «непрозрачность», как описано выше.

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

Джефф
источник
6
Это действительно должен быть принятый правильный ответ. Не показывать страницу, если JS отключен или если есть ошибка JS - плохая идея, и это намного более доступно.
braindigitalis
@Jeff, большое спасибо за это решение! Решил мою проблему!
yathrakaaran
1
Это также не мешает браузерам, в которых отключен CSS (например, пользователи с низкоскоростным доступом к Интернету или инвалиды могут отключить изображения, Javascript и CSS). Opera была, вероятно, самым известным примером браузера, в котором когда-то была кнопка на главной панели инструментов для отключения CSS. Обратной стороной этого подхода является то, что если файл CSS не загружается, страница будет пустой. Например, присвоение имени CSS-файлу "ads.css" приведет к запуску подключаемых модулей блокировки рекламы, и файл не загрузится, в результате чего страница останется полностью пустой. (Конечно, это могло быть намеренно ...)
CubicleSoft
Это метод, который я использую и который мне больше всего нравится; однако я считаю, что мне нужно использовать html{display:none;}в headи html{display:block;}в таблице стилей, чтобы полностью преодолеть FOUC с помощью браузеров на основе Chromium. (У меня не было проблем с темным фоном, установленным на body.)
dotism
Практически нет разницы между этим решением и решением Адама Зернера, разработанным более года назад.
Стефан
17

Решение, не зависящее от jQuery, которое будет работать во всех текущих браузерах и ничего не делать в старых браузерах, включите в свой тег заголовка следующее:

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

Благодаря @justastudent я попытался просто настроить, elm.style.display="none";и, похоже, он работает так, как хотелось, по крайней мере, в текущем Firefox Quantum. Итак, вот более компактное решение, которое пока что является самой простой вещью, которая работает.

<script type="text/javascript">
    var elm=document.getElementsByTagName("html")[0];
    elm.style.display="none";
    document.addEventListener("DOMContentLoaded",function(event) { elm.style.display="block"; });
</script>
Лоуренс Дол
источник
упомянутый код у меня не работал, вот моя версия: попробуйте {var html = document.getElementsByTagName ("html") [0]; document.addEventListener ("DOMContentLoaded", функция (событие) {html.className = '';}); html.className = 'fouc'; } catch (err) {}
Манфред Вуитс,
Мне нравится этот подход, но я хотел бы предложить использование classListAPI.
Просто студент
2
На самом деле, зачем вообще использовать отдельный CSS? Почему бы не сделать, elm.style.display = 'none';а потом исправить elm.style.removeProperty('display');?
Просто студент
@Justastudent: потому что это будет отображать пустую страницу в случае, если Javascript отключен.
Лоуренс Дол
1
@Justastudent: Спасибо. Я пробовал это, и это работает, по крайней мере, в текущих браузерах. Ответ дополнен.
Лоуренс Дол
11

Еще одно быстрое исправление, которое также работает в Firefox Quantum, - это пустой <script>тег в <head>. Однако это ухудшает понимание скорости загрузки страниц и общее время загрузки.

Я добился 100% успеха. Я думаю, что это также основная причина, по которой вышеуказанные решения с другими JS находятся в разработке.

<script type="text/javascript">

</script>
Пол Крим
источник
1
Супер интересно, даже если совершенно ненадежно
маленький крохотный человечек
4

Никто не говорил о CSS @import

Это была проблема для меня, я загружал две дополнительные таблицы стилей прямо в свой файл css с помощью @import

Простое решение: замените все @importссылки на<link />

danidee
источник
Это случилось со мной. Надеюсь, в будущем @importбудет синхронность.
Д.
1

Я придумал способ, который не требует никакого реального изменения кода, уууу! Моя проблема была связана с импортом нескольких файлов css ПОСЛЕ некоторых файлов javascript.

Чтобы решить эту проблему, я просто переместил свои CSS-ссылки так, чтобы они находились над моими импортируемыми javascript-файлами. Это позволило импортировать весь мой CSS и подготовить его к работе как можно скорее, так что когда HTML появится на экране, даже если JS не готов, страница будет правильно отформатирована.

Джейк Бумгаарден
источник
1

Вот мой код ... надеюсь, он решит вашу проблему

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

<script>
    $(document).ready(function() {
        $("body").css('opacity', 1);
    });
</script>
Coding_snakeZ
источник
Удивительно, но среди десятков фрагментов, которые не помогают остановить FOUC - этот действительно работает - для меня. Заметьте, что на корпусе отсутствует конец ", должно быть"<body style="opacity:0;">
abulka
0

Лучшее решение, которое я нашел до сих пор, выглядит так:

  1. Добавьте все стили вашего заголовка в <style/>тег в<head/>

  2. вверху тега стиля добавить .not-visible-first{visibility: hidden}+ другой стиль заголовка

  3. Добавить css через JS в конец тела

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

  4. И не забудьте добавить .not-visible-first{visibility: visible}в конецmain.min.css

Эта опция улучшит взаимодействие с пользователем

Нагибаба
источник
0

Вы можете попробовать это с ванилью

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
источник
0

Самый простой способ, который я знаю, - это скрыть тег html, а затем в нижней части файла javascript добавить тег 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();

Источник: https://gist.github.com/marchershey/139db0e8fd6f03a83578698409d333ce

Марк
источник
1
Обратите внимание, что fadeIn()это метод jQuery, а не собственный JavaScript.
BadHorsie