Sky Archive

HTML

[HTML] The FOUC Problem(화면 깜빡임 현상)

Anchovy ʕ-᷅ᴥ-᷄ʔ 2021. 11. 8. 13:35

FOUC(Flash of Unstyled Content)란?

FOUC는 외부의 CSS가 불러오기 전에 잠시 스타일이 적용되지 않은 웹 페이지가 나타나는 현상이다.

 

이 현상은 스타일이 적용되지 않은 웹 페이지가 스타일이 적용된 웹 페이지로 변화하는 것이다. 웹 브라우저가 웹 페이지에 스타일 정의를 부르고 적용할 때 보이는 부분을 최대한 빨리 수정하지만, 이 변화는 짧지 않은 시간 동안 나타나므로 사용자는 페이지에 오류가 있다는 생각을 하게 된다. 이는 해당 웹문서의 UX를 떨어뜨리는 요인으로 작용한다.

 

※ 처음 이 현상은 2001년 Flash of Unstyled Content이라는 기사에서 문서화되었다. FOUC는 Internet Explorer 특유의 브라우저 문제로 나타났으나 사파리 브라우저에서도 결함이 발견되었고 2006년에 The FOUC Problem란 이름으로 문서화되었다. (이제 사파리의 경우 윈도용 브라우저를 더 이상 지원하지 않는다.)



FOUC 원인

FOUC가 발생하는 주된 원인은 브라우저의 동작 방식과 연관이 있다.

  • 브라우저는 마크업에 참조된 모든 부수적인 파일들을 모아 즉시 DOM(Document Object Model)을 생성
  • 가장 빠르게 분석할 수 있는 글의 내용부분을 화면에 표시
  • 화면에 표시된 내용을 선언된 마크업의 순서에 따라 스타일을 적용하고 스크립트를 실행

최근의 웹 페이지들은 아래와 같은 방법으로 여러 개의 스타일 시트를 참조하는 경향이 있으므로 FOUC는 더 일반적이고 더 빈번하게 관찰된다.

  • 웹 페이지들은 종종 프린터와 무선 장치를 위한 CSS 규칙으로 브라우저 화면 이외의 다른 미디어에 대한 스타일 참조를 포함한다.
  • 웹 페이지는 @import로 스타일 파일을 가져오고, 다른 CSS를 참조할 수 있다.
  • 온라인 광고와 동영상과 검색 엔진같은 다른 곳에서 삽입된 콘텐츠는 종종 코드 블록 내에서 스타일 규칙을 사용한다.
  • 웹 문서가 모두 불러와진 후 자바스크립트를 이용해 DOM 구조를 변경한다.

 

CSS 규칙의 종속적인 성격은 일부 브라우저에서 모든 스타일 데이터를 적용하기 전에 필요한 내용들이 수집될 때까지 기다리기를 권장한다. 스타일이 적용되지 않은 내용이 보이는 것을 방지하기 위해, 개발자는 전체가 로드될 때까지 모든 내용을 숨길 수 있지만 이벤트 핸들러가 실행되고 콘텐츠가 표시되기 전에 종종 마찬가지로 산만한 빈 페이지가 나타날 수 있다. 최근 많이 사용되는 웹폰트의 경우에도 IE 브라우저에서는 FOUC를 유발한다.


- 참조된(@import) CSS
크롬(Chrome), 파이어폭스(Firefox), 오페라(Opera)의 경우, 참조되는 스타일이 적용될 때까지 화면에 표시하지 않지만, IE의 경우 화면에 노출된 상태로 스타일이 적용되어 FOUC를 유발한다. 

- 자바스크립트로 DOM 구조 변경
자바스크립트를 이용해 DOM 구조를 변경하면 대부분의 브라우저가 콘텐츠를 화면에 노출한 상태로 변경되어 FOUC를 유발한다.

 



FOUC 해결책

FOUC를 최소화하기 위해서는 기본적으로 <head> 요소 안에 CSS를 링크하고, @import의 사용을 자제해야 한다.
자바스크립트의 선언순서, 위치를 변경함으로써 극복 가능하거나, 매우 짧아질 수 있다.(성능을 위해 </body> 요소 앞에 자바스크립트를 위치시키곤 하는데 이를 <head> 안으로 위치를 변경해 본다.)
FOUC를 유발하는 구역을 숨겼다가 문서의 스타일이나 스크립트가 모두 적용되면 보여준다.

 

html 태그에 no-js 라는 클래스를 넣어두고 css파일에서 .no-js { display:none; } 처리를 해준다. 그리고 페이지가 모두 로딩이 되고 난 이후에 클래스를 제거(removeClass)하여 막아두었던 페이지를 오픈한다.

단, 스크립트를 사용할 수 없는 브라우저 환경의 경우에는 페이지 노출이 되지 않는 단점이 있고
페이지가 로딩될 동안 빈 페이지가 노출되는것 보다 로딩 중 이미지를 넣어두는 것도 좋은 방법.

 

<html class="no-js">
  <head>
    <style>
      .js #fouc {display: none}
    </style>
    <script>
      (function(H){H.className=H.className.replace(/\bno-js\b/,'js')})(document.documentElement)
    </script>
  </head>
  <body>
    <div id="fouc"> ... </div>
    <script>
      document.getElementById("fouc").style.display="block";
    </script>
  </body>
</html>

 

 

 

 

 

 

 

ref. https://ko.wikipedia.org/wiki/FOUC

https://webdir.tistory.com/416

https://www.paulirish.com/2009/avoiding-the-fouc-v3/