コフス技術ブログ

Safari(WebKit)ではvisibility hiddenの指定があるとwebkit-line-clampが効かない

Safari(macOS, iOS, iPadOS)では、CSSにてvisibility: hidden;が指定された要素もしくはその親を持つ場合、-webkit-line-clampが効かないというバグがあります。

WebKitの古いバグ(2010年に報告あり)の1つで、運良くこれまでこのバグに出会うことなく過ごしてきましたが、とあるプロジェクトで出会いちょっと困ってしまったので忘備録として残そうと思った次第です。

バグの内容

macOS, iOS, iPadOSのSafari(2022/01/04時点)で確認できるバグの1つでvisibility: hidden;が指定されたpタグに-webkit-line-clampを指定し、動的にvisibilityを変更すると省略が効かない状態で表示されます。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    p {
      visibility: hidden;

      display: -webkit-box;
      overflow: hidden;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
    }
  </style>
  <script>
    window.addEventListener('load', () => {
      setTimeout(() => {
        document.querySelector('p').style.visibility = 'visible'
      }, 1000);
    })
  </script>
</head>
<body>
  <main>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum reprehenderit in nisi porro aliquam. Obcaecati voluptates itaque, aperiam sint sapiente, in ipsum repellat blanditiis quasi distinctio officiis facere rerum inventore dolorem ea minus. Dolorem suscipit est accusantium. Sit sed suscipit iure veniam vel quo, laudantium eligendi, aperiam voluptates necessitatibus, similique commodi inventore dolores at consectetur cum iste. Dolore optio quo corrupti alias sequi soluta ratione ut eius vel! Tempore nisi odio non animi? Sit sed aspernatur aliquam assumenda, itaque eum corrupti repellat voluptas. Exercitationem esse distinctio et blanditiis nesciunt aliquid vitae ipsum ratione repellat architecto, ipsa voluptatibus laudantium molestiae. Nam quam quod, cumque modi rerum nisi aut magni voluptate voluptatem atque amet quae necessitatibus impedit laborum qui! Expedita similique natus, quia facilis consequatur enim a facere dolores fuga, magnam qui vel autem architecto est voluptate vero vitae. Quas soluta repudiandae error corrupti praesentium quae, quidem inventore in, dolores sequi quod. Quia quasi culpa necessitatibus aliquid neque eaque incidunt minus, ex pariatur laborum illum vitae alias et error! Reiciendis nihil nostrum ab? Soluta quae laboriosam nesciunt quibusdam? Mollitia ipsum fuga ad veniam provident dignissimos alias beatae iure dolorem assumenda nisi ipsam ex, quam a totam possimus, nobis aut quo. Rerum, odio!</p>
  </main>
</body>
</html>

visibility: hidden;が指定された親を持つ場合も同様に省略が効かなくなります。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      visibility: hidden;
    }
    p {
      display: -webkit-box;
      overflow: hidden;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
    }
  </style>
  <script>
    window.addEventListener('load', () => {
      setTimeout(() => {
        document.getElementsByTagName('body')[0].style.visibility = 'visible'
      }, 1000);
    })
  </script>
</head>
<body>
  <main>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum reprehenderit in nisi porro aliquam. Obcaecati voluptates itaque, aperiam sint sapiente, in ipsum repellat blanditiis quasi distinctio officiis facere rerum inventore dolorem ea minus. Dolorem suscipit est accusantium. Sit sed suscipit iure veniam vel quo, laudantium eligendi, aperiam voluptates necessitatibus, similique commodi inventore dolores at consectetur cum iste. Dolore optio quo corrupti alias sequi soluta ratione ut eius vel! Tempore nisi odio non animi? Sit sed aspernatur aliquam assumenda, itaque eum corrupti repellat voluptas. Exercitationem esse distinctio et blanditiis nesciunt aliquid vitae ipsum ratione repellat architecto, ipsa voluptatibus laudantium molestiae. Nam quam quod, cumque modi rerum nisi aut magni voluptate voluptatem atque amet quae necessitatibus impedit laborum qui! Expedita similique natus, quia facilis consequatur enim a facere dolores fuga, magnam qui vel autem architecto est voluptate vero vitae. Quas soluta repudiandae error corrupti praesentium quae, quidem inventore in, dolores sequi quod. Quia quasi culpa necessitatibus aliquid neque eaque incidunt minus, ex pariatur laborum illum vitae alias et error! Reiciendis nihil nostrum ab? Soluta quae laboriosam nesciunt quibusdam? Mollitia ipsum fuga ad veniam provident dignissimos alias beatae iure dolorem assumenda nisi ipsam ex, quam a totam possimus, nobis aut quo. Rerum, odio!</p>
  </main>
</body>
</html>

一瞬でもレンダリングされると問題ないようで、以下の様にページ表示数ms後にhidden指定を行う場合は問題なく省略が効きます。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    p {
      display: -webkit-box;
      overflow: hidden;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
    }
  </style>
  <script>
    window.addEventListener('load', () => {
      setTimeout(() => {
        document.getElementsByTagName('body')[0].style.visibility = 'hidden'

        setTimeout(() => {
          document.getElementsByTagName('body')[0].style.visibility = 'visible'
        }, 1000);
      }, 10);
    })
  </script>
</head>
<body>
  <main>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum reprehenderit in nisi porro aliquam. Obcaecati voluptates itaque, aperiam sint sapiente, in ipsum repellat blanditiis quasi distinctio officiis facere rerum inventore dolorem ea minus. Dolorem suscipit est accusantium. Sit sed suscipit iure veniam vel quo, laudantium eligendi, aperiam voluptates necessitatibus, similique commodi inventore dolores at consectetur cum iste. Dolore optio quo corrupti alias sequi soluta ratione ut eius vel! Tempore nisi odio non animi? Sit sed aspernatur aliquam assumenda, itaque eum corrupti repellat voluptas. Exercitationem esse distinctio et blanditiis nesciunt aliquid vitae ipsum ratione repellat architecto, ipsa voluptatibus laudantium molestiae. Nam quam quod, cumque modi rerum nisi aut magni voluptate voluptatem atque amet quae necessitatibus impedit laborum qui! Expedita similique natus, quia facilis consequatur enim a facere dolores fuga, magnam qui vel autem architecto est voluptate vero vitae. Quas soluta repudiandae error corrupti praesentium quae, quidem inventore in, dolores sequi quod. Quia quasi culpa necessitatibus aliquid neque eaque incidunt minus, ex pariatur laborum illum vitae alias et error! Reiciendis nihil nostrum ab? Soluta quae laboriosam nesciunt quibusdam? Mollitia ipsum fuga ad veniam provident dignissimos alias beatae iure dolorem assumenda nisi ipsam ex, quam a totam possimus, nobis aut quo. Rerum, odio!</p>
  </main>
</body>
</html>

そのためローカル開発環境などでbrowserSync.stream()を用いている場合、リロード後は省略が効いていないもののスタイルの変更を行っていると省略が効くようになる為気が付き難い厄介さがあります。

調べた限りではこのバグの解決方法は無く、visibilityを使わずに対応する方法が1番の解決手段になります。たとえば単純なコンテンツの表示・非表示であればopacityを使用することで代替が可能です。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      opacity: 0;
    }
    p {
      display: -webkit-box;
      overflow: hidden;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
    }
  </style>
  <script>
    window.addEventListener('load', () => {
      setTimeout(() => {
        document.getElementsByTagName('body')[0].style.opacity = 1
      }, 1000);
    })
  </script>
</head>
<body>
  <main>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum reprehenderit in nisi porro aliquam. Obcaecati voluptates itaque, aperiam sint sapiente, in ipsum repellat blanditiis quasi distinctio officiis facere rerum inventore dolorem ea minus. Dolorem suscipit est accusantium. Sit sed suscipit iure veniam vel quo, laudantium eligendi, aperiam voluptates necessitatibus, similique commodi inventore dolores at consectetur cum iste. Dolore optio quo corrupti alias sequi soluta ratione ut eius vel! Tempore nisi odio non animi? Sit sed aspernatur aliquam assumenda, itaque eum corrupti repellat voluptas. Exercitationem esse distinctio et blanditiis nesciunt aliquid vitae ipsum ratione repellat architecto, ipsa voluptatibus laudantium molestiae. Nam quam quod, cumque modi rerum nisi aut magni voluptate voluptatem atque amet quae necessitatibus impedit laborum qui! Expedita similique natus, quia facilis consequatur enim a facere dolores fuga, magnam qui vel autem architecto est voluptate vero vitae. Quas soluta repudiandae error corrupti praesentium quae, quidem inventore in, dolores sequi quod. Quia quasi culpa necessitatibus aliquid neque eaque incidunt minus, ex pariatur laborum illum vitae alias et error! Reiciendis nihil nostrum ab? Soluta quae laboriosam nesciunt quibusdam? Mollitia ipsum fuga ad veniam provident dignissimos alias beatae iure dolorem assumenda nisi ipsam ex, quam a totam possimus, nobis aut quo. Rerum, odio!</p>
  </main>
</body>
</html>

ただしクリッカブルな要素をvisibilityでコントロールしている場合はopacityに変えるだけだと表示されてないけどクリックできてしまう良くない指定になります。
その場合はdisplay: none;を使うか、イージングを含める場合はJavaScriptにてコントロールが必要になってきます。

Safari(WebKit)以外のモダンブラウザでは生じないので知らずに嵌ると割と原因の特定に時間が掛かってしまいそうです。