かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Mac Catalina WEBでのヒラギノフォント表示問題について考えたメモ

ことの発端

問題点を整理すると

  1. Mac Catalina には ヒラギノフォントがバンドルされていない?
  2. Chrome77 は font-family: 'Hiragino Kaku Gothic', 'ヒラギノ角ゴ ProN' の指定が無効になっている?
  3. Chrome77 では font-family: sans-serif の指定があっても serif で表示されてしまう?

3 に関しは ChromeMac OS の問題とかバグと思われるので考慮しなくても良さそう。
なので問題は 1 と 2 の場合。またはその両方のパターン。
1 の Mac Catalina にヒラギノフォントがそもそもバンドルされていないのであれば、2 の可能性は無いので CSSfont-familyMac Catalina でも良き感じに表示できる別の日本語フォント指定を追加すればOKかなという肌感。

1. Mac Catalina にヒラギノフォントはバンドルされていない?

バンドルされているフォントは apple が公開している macOS Catalina に組み込まれているフォント - Apple サポート

組み込みフォントのリストには Hiragino Sans があり、ヒラギノ角ゴシック ProN に該当するフォントは「書類をサポートするために使えるフォント」のリストにある。ヒラギノフォントの表記が Hiragino Sans になった変更は High Sierra (OS 10.13) の時点のようなので、Mac Catalina にヒラギノ フォントがバンドルされていない訳ではなく、Chrome で表示した際に font-family: 'Hiragino Kaku Gothic', 'ヒラギノ角ゴ ProN'のような指定で Hiragino Sans が表示されなくなっているという問題のように思われる。

つまり、
Mac Catalina にヒラギノフォントはバンドルされている。
名称が Hiragino Sans になっている。但しその変更は High Sierra (OS 10.13) の時点 で行われている

2. Chrome77 は font-family: 'Hiragino Kaku Gothic', 'ヒラギノ角ゴ ProN' の指定が無効になっている?

この可能性が高いと思われる。
名称が Hiragino Sans になっているので、これを font-family の指定に追加すれば良さそう

例えば現状がこんな指定なら

body {
  font-family: "Hiragino Kaku Gothic ProN", "ヒラギノ角ゴ ProN W3", sans-serif;
}

👇 Hiragino Sans を追加する

body {
  font-family: "Hiragino Kaku Gothic ProN", "ヒラギノ角ゴ ProN W3", "Hiragino Sans", "ヒラギノ角ゴシック", sans-serif;
}

こうすれば Hiragino Kaku Gothic ProN, ヒラギノ角ゴ ProN W3 で該当フォントがなければ Hiragino Sans が使用される筈です。
合わせて system-ui-apple-system, BlinkMacSystemFont を使用しておけばより安全だと思います。

system-ui

Chromesystem-ui を指定した場合、MaciOSではSan Franciscoになる(ヒラギノ角ゴシックは含まれていない)。Windows 10ではYu Gothic UIで、Windows 8.1以前ではSegoe UIとMeiryoの混植。AndroidではRobotoとNotoの混植。
system-uisans-serifなどと同じ総称フォントファミリーだ。CSS Fonts Module Level 4で追加された。プラットフォームのUIと同じフォントを利用できる。現状ではChromeのみで実装されており、その他のブラウザのためにはフォールバックを書く必要がある。
cf. 日本語向けフォントスタックの現状 - yuhei blog

-apple-system

iOS9からのシステムフォント San Francisco が使用される
cf. 2020年まで使えるfont-familyおすすめゴシック体 - Qiita

BlinkMacSystemFont

-apple-systemと同じSan Franciscoが適用されます。
-apple-systemと何が違うかというと、こちらはBlink(フォント名がそのままです)、WebKitから派生したレンダリングエンジン用フォントです。 このレンダリングエンジンを使用しているのはChromeOpera。この両ブラウザは、先に記述した-apple-systemではなく、こちらが適用されることになります。
純粋なWebKitであるSafari-apple-systemが適用されます。
cf. 2020年まで使えるfont-familyおすすめゴシック体 - Qiita

Mac Catalina でも使える font-family 案
body {
  font-family: system-ui, -apple-system, BlinkMacSystemFont, 
    "Helvetica Neue", "Hiragino Sans", "Hiragino Kaku Gothic ProN",
    "ヒラギノ角ゴ ProN W3", Meiryo, "メイリオ", sans-serif;
}

font-weight 問題

Hiragino Sans は W0 〜 W9 のウェイトが用意されているので、font-weight が Hiragino Kaku Gothic とは異なる可能性があります。
簡単なテーブルを作成して表示させてみました。※ クリーンな Catalina 環境ではないので実際のものと異なっている可能性はあります

Hiragino Sans vs. Hiragino Kaku Gothic

sample

See the Pen Hiragino Sans vs. Hiragino Kaku Gothic by KIKIKI (@chaika-design) on CodePen.

Hiragino Kaku Gothic の font-weight: bold は Hiragino Sans の font-weight: 600 に相当するように見えます。
Hiragino Kaku Gothic は font-weight: 600 以上はどれも同じウェイトなので Hiragino Sans でも Hiragino Kaku Gothic でも同じウェイトにしたいということであれば数値指定の font-weight: 600 にしたほうが良さそうです。 font-weight: boldfont-weight: bolder はもしかしたら W9 の極太フォントで表示されるのか?という懸念があったのですが、Chrome 環境でぱっと見る感じ font-weight: bold 指定と変わらなそうなので一安心しました。

まとめ

CSSヒラギノフォントを指定する場合 font-family には Hiragino Sans の指定が入ってないなら追加しておこう。
なんなら system-ui, -apple-system, BlinkMacSystemFont の指定も入れておけばより安全になりそう。

font-weightbold 指定だと Hiragino Sans は Hiragino Kaku Gothic より少し太くなる。
数値で 600 を指定すれば同等の太さになる。ただし、英数に別のフォントが当たるようにしている場合少し細くなる可能性がある。
何れにせよ、どのウェイトを表示させるのかってのはフォント自体の設計に拠る部分が大きいと思うので英数は別のフォントが表示される指定になっているCSSの場合は目視チェックでバランスを確認しておくのが良さそうだなと思いました。

CSS のフォント指定ムズィ!


[参照]

ほんとに、フォント。 フォントを活かしたデザインレイアウトの本

ほんとに、フォント。 フォントを活かしたデザインレイアウトの本

  • 作者:ingectar-e
  • 出版社/メーカー: ソシム
  • 発売日: 2019/02/20
  • メディア: 単行本(ソフトカバー)

SCSS の !default フラグ についてのメモ

変数に !default フラグを付けて定義すると、変数が定義されてないか値が null の場合のみ値が設定されるようになる

g.e.
!default フラグなし

$base-color: #333;
$base-color: #000; // 後から出てきたもので上書きされる
body {
  color: $base-color; // => #000
}

!default フラグあり

$base-color: #333;
$base-color: #000 !default; // 既に定義されているので無視される
body {
  color: $base-color; // => #333
}

!default フラグしかない場合は最初に登場した値がセットされる

$base-color: #333 !default; // 定義されてない変数なので定義される
$base-color: #000 !default; // 既に定義されているので無視される
body {
  color: $base-color; // => #333
}

最後までファイルを捜査してからコンパイルされる訳ではない

変数の指定やスタイルの定義の順番には気をつける必要がある

// ライブラリとか
$font-style: italic !default;
.p1 {
  font-style: $font-style;
}

// 独自のスタイル
$font-style: normal; // 指定を上書き
.p2 {
  font-style: $font-style;
}

👇 コンパイル

.p1 { font-style: italic; }
.p2 { font-style: normal; }

.p1 のスタイルを定義している段階では変数は上書きされていない
.p1.p2 も同じにしたい場合は独自のスタイルの変数が先に書かれてないとダメだった

// 独自の変数
$font-style: normal;

// ライブラリとか
$font-style: italic !default; // 既に定義されているので無視される
.p1 {
  font-style: $font-style;
}

// 独自のスタイル
.p2 {
  font-style: $font-style;
}

👇 コンパイル

.p1 { font-style: normal; }
.p2 { font-style: normal; }

sample

See the Pen SCSS !default keyword by KIKIKI (@chaika-design) on CodePen.

所感

ライブラリの中で指定されているスタイルを変更できる素晴らしい仕組みという事は理解できるが、ライブラリ内で!defaultで定義され指定されているスタイルを独自のスタイルに変更するには、独自のスタイルの変数だけを先に記述してからライブラリを読み込ませる構成にせざるを得ないので、先頭でまとめてライブラリを import にできないのに若干の気持ち悪さを感じる…

例 ライブラリ内のスタイルを変更できる構成
ライブラリ base.scss

$base-color: #000 !default;

body {
  color: $base-color;
}
p {
  margin: 0 0 14px;
}

main.scss

// 独自の変数定義
$base-color: #333;

// ライブラリの読込み
@import base;

// その他のスタイルやライブラリのスタイルを変更する独自のCSS
p {
  margin: 1em 0;
}

SCSS 難解…


[参考]

国家は破綻する――金融危機の800年

国家は破綻する――金融危機の800年

デフォルト…

Ruby メソッド定義 (def式) 内でメソッド定義 (def式)した場合のメモ

Rubyのお勉強をしていてメソッド定義内でメソッド定義したら不思議な挙動 (JS脳には予想外だっった) だったのでメモ。

メソッド定義 (def式) 内に メソッド定義 (def式) をした場合

def a
  puts 'A'
  def b
    puts 'B'
  end
  print "self.b > "
  self.b
end

a
# => "A"
# => "self.b > B"
b
# => "B"

えっ? def a 内で定義した def bdef a の外からでも呼び出せるの…!?
JS脳的には下記のようなイメージだったのでびっくりしました

function a() {
  console.log('a')
  function b () {
    console.log('b')
  }
  b()
}
a()
// a
// b
b()
// Error: Uncaught ReferenceError: b is not defined

Ruby のメソッド定義 (def式) は呼び出されるとトップレベルに定義される?

Ruby では def式 の書かれている場所を通れば、そのファイル?のトップレベルにメソッドが定義されるのかなという印象を持ちました。

def a
  puts 'A'
  def b
    puts 'B'
  end
end

a # => "A"
b # => "B"

a を呼び出してないと b は未定義になる

def a
  puts 'A'
  def b
    puts 'B'
  end
end
b
# => undefined local variable or method `b` for main:Object

Ruby は関数ではなくメソッドで、レシーバー.関数名 引数 の形で呼び出されるとあったので、def式で定義すると、そのファイルのトップレベルのオブジェクトがレシーバーになるからトップレベルから呼び出せるのかな〜?とか考えていました。詳しくはないので完全に憶測なのですが…

メソッド定義 (def式) は後から呼び出されたもので上書きされる?

先の実験でメソッド定義内にあるメソッド定義は外側のメソッドを呼び出した際に定義されることがわかりました。
という事は同じ名前のメソッドが外側にもある場合、メソッドの呼び出し順によって、呼び出されるメソッド上書きされが変わってしまう可能性があるのではないかと思い試してみました。

def a
  puts 'A'
  b
  def b
    puts 'B inside A'
  end
  b
end

def b
  puts 'B'
end

b # => "B" … トップレベルのメソッドが呼び出される

a
# => "A"
# => "B" … メソッド内の def b の定義を通る前なので、外側のトップレベルのメソッドが呼び出されている
# => "B inside A" …  a 内の b メソッドが定義され、新しく定義された b が呼び出されている

b # => "B inside A"
# トップレベルの b メソッドは a 内で定義された方に上書きされてしまっている

予想通りでした。
Ruby の場合同じファイル内でメソッド定義する場合はメソッド名が重複しないように気をつける必要がありそうです。
そもそもトップレベルにつらつら定義するのが Ruby 的お作法では良くないのかも? この辺りの文化については詳しくないのでどこで学べば良いのでしょう…?

ポエム

Ruby のメソッド定義内でメソッド定義したらメソッド外で呼び出したらエラーになるよね〜って思って実行したらふつーに呼び出せてしまってびっくりしました。慣れ親しんでる JavaScript の関数定義と違ってRuby の メソッドて定義 (def式) は常にトップレベルに定義されるって感じっぽいのですね。JavaScript感覚で使ってるとハマりそうでした。

Ruby は関数じゃなくてメソッドって呼ぶのなんでだろう?慣習???みたいに思ってたのですが、今回のハマりで読んでたRubyの本

レシーバーに含まれる情報を使用しないメソッドを関数的メソッドと呼ぶ。全てのメソッドはレシーバー情報を持っているので純粋な関数ではない
初めてのRuby 著 Yugui

みたいな感じに書かれていて、オブジェクトに紐付いてて呼び出し元(レシーバー)の情報を持っているとメソッド?
トップレベルに置かれた def式 は mail オブジェクトとかに紐付いててその情報持ってるってこと??
って事は JavaScript はブラウザで実行したらfunction も全部 window オブジェクトに紐づいて window.func() で呼び出せるから関数じゃなくて本当はメソッドなん???
むむむ?????
と解ったよーな、解らんよーな感じになりました。
ナルホドわからん!! 俺は雰囲気でぷろぐらむを描いている!!!!


初めてのRuby

初めてのRuby

プログラミング言語 Ruby

プログラミング言語 Ruby