sikaku

iOSでのCSS,blur関数最小値について

iOS,iPadOSだとfilterプロパティなんかのblur()関数使用時の最小値は0を除くと1pxだったんだねって話です。

前書き

スクショ_iPad

iPadからCSSとHTMLでチョコ作成を確認していたのですが、表示がこの有様でした。

すっごいボケてる。下の「ほぼ誤差レベル」がギャグにしか見えない。

ぼかしの指定がfilter:blur(0.3px)なのですが、目算1pxはボケています。

確認ブラウザがsafariだったので、別ブラウザ(firefox,chrome)も試しましたが表示は変わらず。おそらくOS側の仕様じゃないかなーと推察。 iphoneでも同様。macは未所持の為確認できず。

調べても特に情報が出なかったので備忘録として残しておきます。

スクショ_android

ちなみに自前泥での表示はブラウザ差異なくこれでした。windowsも概ね同様。

検証

前提確認

スクショ_iPad
スクショ_android

上記スクリーンショットは同指定内容を確認したipad,androidのもの。

指定詳細

左から

filter: blur(0);

filter: blur(0.3px);

filter: blur(0.6px);

filter: blur(1px);

androidで差が視認できるのに対し、ipadでは0.3px-1px間で差異が見受けられない。

この段階で考えられるiOS系のblur()関数の仕様が下記いずれかとなる。

  • 小数点以下の指定が無効
  • px指定時のみ小数点以下の指定が無効
  • 1以下の小数での指定が無効
  • 特定値以下のぼかし不可

ちなみに前述したが、結論を先んじて述べると特定値以下のぼかし不可が該当する。

実検証

px単位使用時の小数の有効性証明
スクショ_iPad_1px-2px指定
  • px単位使用時の小数の有効性証明の為、1px2px間での比較
  • 各指定毎に描画が異なるのが見てとれる為、下記二点は異なると証明できる。
    • 小数点以下の指定が無効
    • px指定時のみ小数点以下の指定が無効
指定詳細

左から

filter: blur(1px);

filter: blur(1.3px);

filter: blur(1.6px);

filter: blur(2px);

1以下小数の有効性証明
スクショ_iPad_0-1em指定
  • 文字サイズ基準のemでの数値指定(検証時の文字サイズ10px)
  • 各指定毎に描画が異なるのが見てとれる為、下記一点は異なると証明できる。
    • 1以下の小数での指定が無効
指定詳細

左から

filter: blur(0);

filter: blur(0.3em);(実質3px)

filter: blur(0.6em);(実質6px)

filter: blur(1em);(実質10px)

px以外の単位で1px以下の描画可能か検証
スクショ_iPad_0-0.1em指定
  • 文字サイズ基準のemでの数値指定(検証時の文字サイズ10px)
  • 0以外の差異が見てとれず、0.1em(実質1px)と同描画となっていると見受けられる。
  • 上記検証含め、この時点で下記が仕様に該当するのではないかと推察される
    • 特定値以下のぼかし不可
  • しかし、これも今指定使用の小数第二位無効という可能性がある為次の検証をする。
指定詳細

左から

filter: blur(0);

filter: blur(0.03em);(実質0.3px)

filter: blur(0.06em);(実質0.6px)

filter: blur(0.1em);(実質1px)

em単位指定時の小数第二位有効性証明
スクショ_iPad_0-0.1em_1em=50px指定
  • 基準となる文字サイズを50pxに変更したうえでの上記と同指定の検証
  • こちらでは各指定毎に明確に描画が異なるのが見て取れる為、小数第二位の指定自体は有効と証明できる
指定詳細

左から

filter: blur(0);

filter: blur(0.03em);(実質1.5px)

filter: blur(0.06em);(実質3px)

filter: blur(0.1em);(実質5px)

おまけ

calc関数を併用してみる
スクショ_iPad_calc関数使用
  • calc()関数使えばワンチャンないかなーと思ったが、当然のようにチャンスなど無い。
指定詳細

左から

filter: blur(0);

filter: blur(calc( 1px / 3 ));(実質0.333...px)

filter: blur(calc( 2px / 3 ));(実質0.666...px)

filter: blur(clac( 3px / 3 ));(実質1px)

scale関数を利用してみる
スクショ_iPad_scale関数使用
  • 幅高さ、ボーダー幅文字サイズ諸々、ぼかし範囲も含め全サイズ10倍数値を指定した上で、transform:scale(0.1,0.1);で縮小表示
  • 0.3px等指定時のandroidと遜色ない表示。
  • 最小値が決まってる系はこの手に限る。(面倒だからやりたくはない)
指定詳細

左から

filter: blur(0);

filter: blur(3px);(実質0.3px)

filter: blur(6px);(実質0.6px)

filter: blur(10px);(実質1px)

他利用での1px以下小数

iOS系でも、他での利用だと1px以下の小数指定でしっかり描画してくれるんですよね。

左のスクショ

赤:width: 0.5px;

青:width: 1px;

※すごく拡大した上でのスクショです

検証用ページについて

検証用ページ

  • 表示の統一性を出す為大き目のサイズ構成にしています。そのためスマホからは横スクロールがでると思います。
  • iOSでの表示確認が主目的の為、ベンダープレフィックスはつけていません。(ものぐさでごめんなさい)

ソースコード

HTML
  1. <ul id="demolist">
  2. <li id="demo0">
  3. <span></span><span></span><span></span><span></span>
  4. </li>
  5. <li id="demo1">
  6. <span></span><span></span><span></span><span></span>
  7. </li>
  8. <li id="demo2">
  9. <span></span><span></span><span></span><span></span>
  10. </li>
  11. <li id="demo3">
  12. <span></span><span></span><span></span><span></span>
  13. </li>
  14. <li id="demo4">
  15. <span></span><span></span><span></span><span></span>
  16. </li>
  17. <li id="demo5">
  18. <span></span><span></span><span></span><span></span>
  19. </li>
  20. <li id="demo6">
  21. <span></span><span></span><span></span><span></span>
  22. </li>
  23. </ul>
CSS
  1. @import url(https://fonts.googleapis.com/css?family=Source+Code+Pro);
  2. * ,*::before ,*::after {
  3. box-sizing: border-box;
  4. margin: 0;
  5. padding: 0;
  6. }
  7. body {
  8. min-width: 0;
  9. text-align: center;
  10. font-size: 12px;
  11. font-family: 'Source Code Pro',monospace;
  12. }
  13. #demolist {
  14. display: inline-block;
  15. width: 520px;
  16. margin: 0 auto;
  17. padding: 0 20px;
  18. list-style-type: none;
  19. }
  20. #demolist > li {
  21. display: flex;
  22. justify-content: space-between;
  23. margin: 25px 0;
  24. }
  25. #demolist span {
  26. position: relative;
  27. width: 23%;
  28. }
  29. #demolist span::before {
  30. content: 'text';
  31. display: block;
  32. padding: calc( 50% - 5px ) 0;
  33. border: solid 5px blue;
  34. font-size: 10px;
  35. line-height: 0;
  36. }
  37. #demo0 span:nth-of-type(1)::before { filter:blur(0)}
  38. #demo0 span:nth-of-type(1)::after { content: '0'}
  39. #demo0 span:nth-of-type(2)::before { filter:blur(0.3px)}
  40. #demo0 span:nth-of-type(2)::after { content: '0.3px'}
  41. #demo0 span:nth-of-type(3)::before { filter:blur(0.6px)}
  42. #demo0 span:nth-of-type(3)::after { content: '0.6px'}
  43. #demo0 span:nth-of-type(4)::before { filter:blur(1px)}
  44. #demo0 span:nth-of-type(4)::after { content: '1px'}
  45. #demo1 span:nth-of-type(1)::before { filter:blur(1px)}
  46. #demo1 span:nth-of-type(1)::after { content: '1px'}
  47. #demo1 span:nth-of-type(2)::before { filter:blur(1.3px)}
  48. #demo1 span:nth-of-type(2)::after { content: '1.3px'}
  49. #demo1 span:nth-of-type(3)::before { filter:blur(1.6px)}
  50. #demo1 span:nth-of-type(3)::after { content: '1.6px'}
  51. #demo1 span:nth-of-type(4)::before { filter:blur(2px)}
  52. #demo1 span:nth-of-type(4)::after { content: '2px'}
  53. #demo2 span:nth-of-type(1)::before { filter:blur(0)}
  54. #demo2 span:nth-of-type(1)::after { content: '0'}
  55. #demo2 span:nth-of-type(2)::before { filter:blur(0.3em)}
  56. #demo2 span:nth-of-type(2)::after { content: '0.3em'}
  57. #demo2 span:nth-of-type(3)::before { filter:blur(0.6em)}
  58. #demo2 span:nth-of-type(3)::after { content: '0.6em'}
  59. #demo2 span:nth-of-type(4)::before { filter:blur(1em)}
  60. #demo2 span:nth-of-type(4)::after { content: '1em'}
  61. #demo3 span:nth-of-type(1)::before { filter:blur(0)}
  62. #demo3 span:nth-of-type(1)::after { content: '0'}
  63. #demo3 span:nth-of-type(2)::before { filter:blur(0.03em)}
  64. #demo3 span:nth-of-type(2)::after { content: '0.03em'}
  65. #demo3 span:nth-of-type(3)::before { filter:blur(0.06em)}
  66. #demo3 span:nth-of-type(3)::after { content: '0.06em'}
  67. #demo3 span:nth-of-type(4)::before { filter:blur(0.1em)}
  68. #demo3 span:nth-of-type(4)::after { content: '0.1em'}
  69. #demo4 span::before {
  70. font-size: 50px;
  71. letter-spacing: -0.2em;
  72. }
  73. #demo4 span:first-letter {
  74. margin-left: -0.2em;
  75. }
  76. #demo4 span:nth-of-type(1)::before { filter:blur(0)}
  77. #demo4 span:nth-of-type(1)::after { content: '0'}
  78. #demo4 span:nth-of-type(2)::before { filter:blur(0.03em)}
  79. #demo4 span:nth-of-type(2)::after { content: '0.03em'}
  80. #demo4 span:nth-of-type(3)::before { filter:blur(0.06em)}
  81. #demo4 span:nth-of-type(3)::after { content: '0.06em'}
  82. #demo4 span:nth-of-type(4)::before { filter:blur(0.1em)}
  83. #demo4 span:nth-of-type(4)::after { content: '0.1em'}
  84. #demo5 span:nth-of-type(1)::before { filter:blur(0)}
  85. #demo5 span:nth-of-type(1)::after { content: '0'}
  86. #demo5 span:nth-of-type(2)::before { filter:blur(calc(1px / 3))}
  87. #demo5 span:nth-of-type(2)::after { content: 'calc(1px / 3)'}
  88. #demo5 span:nth-of-type(3)::before { filter:blur(calc(2px / 3))}
  89. #demo5 span:nth-of-type(3)::after { content: 'calc(2px / 3)'}
  90. #demo5 span:nth-of-type(4)::before { filter:blur(calc(3px / 3))}
  91. #demo5 span:nth-of-type(4)::after { content: 'calc(3px / 3)'}
  92. #demo6 span::before {
  93. position: absolute;
  94. top: 0; left: 0;
  95. width: 1000%;
  96. padding: calc( 500% - 50px ) 0;
  97. border-width: 50px;
  98. font-size: 100px;
  99. transform: scale(0.1,0.1);
  100. transform-origin: top left;
  101. }
  102. #demo6 span::after {
  103. display: block;
  104. padding-top: 100%;
  105. }
  106. #demo6 span:nth-of-type(1)::before { filter:blur(0)}
  107. #demo6 span:nth-of-type(1)::after { content: '0'}
  108. #demo6 span:nth-of-type(2)::before { filter:blur(3px)}
  109. #demo6 span:nth-of-type(2)::after { content: '3px'}
  110. #demo6 span:nth-of-type(3)::before { filter:blur(6px)}
  111. #demo6 span:nth-of-type(3)::after { content: '6px'}
  112. #demo6 span:nth-of-type(4)::before { filter:blur(10px)}
  113. #demo6 span:nth-of-type(4)::after { content: '10px'}