LoginSignup
2
2

More than 5 years have passed since last update.

CSSやJSの読み方次第でgetComputedStyle()で想定通りのスタイルの値が取れないことがある

Last updated at Posted at 2017-06-24

以下のような挙動があって混乱したのでメモ。

ファイル構成

index.html
<link rel="stylesheet" href="main.css">
<script src="main.js" async></script>
main.css
@import url("external.css");

html {
  font-size: 62.5%;
}
external.css
/* empty file */
main.js
console.log(getComputedStyle(document.body).fontSize)

setTimeout(function () {
  console.log(getComputedStyle(document.body).fontSize)
}, 500)

コンソールへの出力結果

想定した出力

10px
10px

実際の出力

16px
10px

つまり…

最初のconsole.log()時に以下のスタイルが未適用の状態になっているっぽい。

html {
  font-size: 62.5%;
}

回避方法

追記:実際には回避できてないかもしれないので↓のコメントも参照。

1. @importを使わずlinkタグで読み込む

index.html
+<link rel="stylesheet" href="external.css">
 <link rel="stylesheet" href="main.css">
 <script src="main.js" async></script>
main.css
-@import url("external.css");
-
 html {
   font-size: 62.5%;
 }

2. linkタグを使わずstyleでHTML内に直接書く

index.html
+<style>
+@import url("external.css");
+
+html {
+  font-size: 62.5%;
+}
+</style>
 <script src="main.js" async></script>
main.css
-@import url("external.css");
-
-html {
-  font-size: 62.5%;
-}

3. scriptタグのasync属性を使わずコード内でDOMContentLoadedイベントを待つ

index.html
 <link rel="stylesheet" href="main.css">
-<script src="main.js" async></script>
+<script src="main.js"></script>
main.js
+document.addEventListener('DOMContentLoaded', function () {
+
 console.log(getComputedStyle(document.body).fontSize)

 setTimeout(function () {
   console.log(getComputedStyle(document.body).fontSize)
 }, 500)
+
+})
  • diffを見やすくするためインデントは省略。

4. scriptタグ内にJSを書く

index.html
 <link rel="stylesheet" href="main.css">
-<script src="main.js" async></script>
+<script>
+document.addEventListener('DOMContentLoaded', function () {
+  console.log(getComputedStyle(document.body).fontSize)
+
+  setTimeout(function () {
+    console.log(getComputedStyle(document.body).fontSize)
+  }, 500)
+})
+</script>
main.js
-console.log(getComputedStyle(document.body).fontSize)
-
-setTimeout(function () {
-  console.log(getComputedStyle(document.body).fontSize)
-}, 500)
  • 以下のようにbody後にscriptを配置してDOMContentLoadedを使わない形も可。
index.html
 <link rel="stylesheet" href="main.css">
-<script src="main.js" async></script>
+<body></body>
+<script>
+console.log(getComputedStyle(document.body).fontSize)
+
+setTimeout(function () {
+  console.log(getComputedStyle(document.body).fontSize)
+}, 500)
+</script>

5. 何もしないscriptタグを挿入する

index.html
 <link rel="stylesheet" href="main.css">
+<script> </script>
 <script src="main.js" async></script>
  • <script></script>ではダメで、スペースを入れる必要がある。

6. @importを後ろに持ってくる

main.css
-@import url("external.css");
-
 html {
   font-size: 62.5%;
 }
+
+@import url("external.css");
  • 当然これによって評価順序が変わるので注意。

感想

難しいなぁ。なんかバグっぽいと思ったけど、Chrome、Firefox、Safariで同じ挙動だったので、おそらく仕様で決まっているのかも。

2
2
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2