かもメモ

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

HTML 本当は怖い target="_blank" 。rel="noopener" ってなに?

WordPressの投稿で別ウィンドウで開くリンクtarget="_blank"を作成すると、

<a href="{URL}" target="_blank" rel="noopener">LINK TEXT</a>

のようなrel="noopener"属性を持ったaタグが出力されます。

rel="noopener" の意味

1. target="_blank" のセキュリティ上の脆弱性の問題を避ける

Without this, the new page can access your window object via window.opener. Thankfully the origin security model of the web prevents it reading your page, but no-thankfully some legacy APIs mean it can navigate your page to a different URL using window.opener.location = newURL.
出典: The performance benefits of rel=noopener - JakeArchibald.com

target="_blank"で開かれたページは、元のページをwindow.openerオブジェクトとして持つので、リンク先のページからwindow.opener.location = "danger site url" のように元ページを操作することが出来てしまうようです。

rel="noopener" を使うことで、新しく開いたページからwindow.openerオブジェクトを使って元ページの操作をできなくできるようです。no・openerですね。

DEMO
noopener DEMO

noopener demo page | github.io

rel="noopener"のないリンク先から元ページを操作しているのが解るかと思います。

2. パフォーマンス低下の問題を避ける

This means JavaScript running on one domain runs on a different thread to a window/tab running another domain.
However, due to the synchronous cross-window access the DOM gives us via window.opener, windows launched via target="_blank" end up in the same process & thread. The same is true for iframes and windows opened via window.open.

出典: The performance benefits of rel=noopener - JakeArchibald.com

target="_blank"で開かれたページは、元ページとJavaScriptが同じプロセス・スレッドで動作するようです。
なので、target="_blank"で開かれたページに負荷の高いJavaScriptが実行されていると、元ページのパフォーマンス低下など影響がある可能性があるようです。

Google的見解

監査に合格する方法
レポートを確認して、Lighthouse で特定された各リンクに rel="noopener" を追加します。 一般的に、外部リンクを新しいウィンドウまたはタブで開く場合は、必ず rel="noopener" を追加してください。
出典: Links to cross-origin destinations are unsafe

Goolge的には基本的にtarget="_blank"を使用したリンクにはrel="noopener"をつけたほうが良さそうな雰囲気っぽいです。
 

JavaScriptから元ページを操作できるのってJavaScriptwindow.open()した時だと思っていました。
まさかHTMLのリンクタグのtarget="_blank"からも操作できるとは思ってなかったです… そして、target="_blank"で開かれたページが元ページと同じプロセスになるってのは、開かれたページからwindow.openerが使えるって部分からなんとなく納得。
というか同じプロセスになる仕様だからwindow.openerが使えちゃうってって感じでしょうか?

それよりtarget="_blank"で新しく開いたページからwondow.openerで元ページを操作できるってのが衝撃的だったので、新しく開くリンクにはrel="noopener"積極的につけていこうと思いました。

追記 rel="noopener" のサポート状況

I can useでみてみると… 2018年1月末の状態で、
rel="noopener" 対応状況 Can I use... Support tables for HTML5, CSS3, etc

IEはまぁうん。しかしEdge… お前もダメなのか…
という状況のようです。


[参考]

おまけ rel 属性 のメモ
意味
nofollow 重要でないリンク・リンク先のリンクをクロールしない
信頼できないコンテンツ・ユーザー投稿に含まれるリンクなどに指定
noreferrer リンク先にリファラを送信しない
noopener リンク先のページでwindow.openerによる元ページの操作を禁止する
alternate 代替ドキュメントへのリンク
author 著者へのリンク
license ライセンス文章へのリンク
help ヘルプへのリンク
bookmark このページをブックマークできる固定リンク
prev 前のページへのリンク
next 次のページへのリンク
prefetch リンク先を予めキャッシュする
tag このページのタグ
search 検索機能
icon アイコン・ファビコンとか e.g. <link rel="icon" href="/favicon.ico">
stylesheet CSSの読み込み ※ linkタグのみで使用可

昔のWordPresstarget="_blank"のリンクに出力されるのrel="noreferrer"だったような気がしてたのですが、
WordPress v4.7.4 以降では rel="noreferrer noopener"で、
WordPress v4.8 から rel="noopener" だけになったみたいです。
テーマ作ってばかりで管理画面からの投稿はほぼ使ってないので気づいてませんでした…
(定期的にソース開く癖つけないとダメですね)

[参考]

CSS 何だったけってなりがちなメモ。initial と inherit

CSSのプロパティリセットする時に使うやつ。
initialinherit
CSS書かない日が続くとどっちが何だっけ?ってなることがあるのでメモ。(メモすれば忘れにくくなる!かも

initial は 初期化

英語で initial「初めの、最初の、初期の」とか。
プログラムとかでよく出てくるinitとかと同じ

CSSinitial キーワードは、要素にプロパティの初期値 (または既定値) を設定します。
初期値をブラウザースタイルシートで指定された値と混同しないでください。
出典: initial - CSS: カスケーディングスタイルシート | MDN

HTML

<p class="text-red">
  おいでよ<em>アイカツ</em>の沼!
</p>

<p class="text-red">
  おいでよ<em class="text-initial">アイカツ</em>の沼!
</p>

CSS

.text-red   { color: red; }
.text-initial { color: initial; }

👇

See the Pen note. CSS initial by KIKIKI (@chaika-design) on CodePen.

note.

初期値
CSS プロパティの 初期値 (initial value)は、定義表に挙げられている既定値です。初期値の使い方はプロパティが継承されているかどうかで異なります。

  • 継承プロパティでは、初期値はルート要素に対してのみ、特定の値が指定されていない場合に限り使用されます
  • 非継承プロパティでは、初期値はすべての要素において、特定の値が指定されていない場合に限り使用されます。
出典: 初期値 - CSS: カスケーディングスタイルシート | MDN

inherit は親要素のプロパティを継承

英語で inherit「受け継ぐ、相続する、遺伝する」とか。

CSS の inherit キーワードは、要素のプロパティの計算値を親要素から取得するよう指定します。
出典: inherit - CSS: カスケーディングスタイルシート | MDN

margin, padding, border, background などは、普段は子要素に継承されませんが、inherit を指定することで、子要素(classB)でも margin, padding, border, background が適用されます。 通常では継承されないスタイルを親要素から継承させたり、継承することを明示的に示したい場合に使用されます。 CSS - inherit

colorとかfont-sizeとか継承されるプロパティ以外も親要素に合わせるという事っぽい

HTML

<span>Soleil</span>
<ul class="list">
  <li class="text-red">
    <span>星宮いちご</span>
  </li>
  <li class="text-blue">
    <span>霧矢あおい</span>
  </li>
  <li class="text-purple">
    <span>紫吹蘭</span>
  </li>
  <li class="text-green">
    <i>ジョニー別府</i>
  </li>
</ul>

<span>Soleil</span>
<ul class="list">
  <li class="text-red">
    <span class="text-inherit">星宮いちご</span>
  </li>
  <li class="text-blue">
     <span class="text-inherit">霧矢あおい</span>
  </li>
  <li class="text-purple">
    <span class="text-inherit">紫吹蘭</span>
  </li>
  <li class="text-green">
    <i class="text-inherit">ジョニー別府</i>
  </li>
</ul>

CSS

span { color: orange; }
.text-red    { color: red; }
.text-blue   { color: blue; }
.text-purple { color: purple; }
.text-green  { color: green; }
.text-inherit { color:  inherit; }

.list .text-red    { border-bottom: 1px solid red; }
.list .text-blue   { border-bottom: 1px solid blue; }
.list .text-purple { border-bottom: 1px solid purple; }
.list .text-inherit { border: inherit; }

👇

See the Pen note. CSS inherit by KIKIKI (@chaika-design) on CodePen.

colorだけでなく、borderも親要素のものが継承されています

unset

CSSunset キーワードはプロパティをリセットし、親からの継承された場合は継承値、そうでなければ初期値を設定します。
出典: unset - CSS: カスケーディングスタイルシート | MDN

親要素から継承される属性に対しては inherit と同じ動作を、継承されない属性に対しては initial と同じ動作をします。
出典: CSS - unset

unsetは少しややこしいですが、

  • colorfont-sizeのような継承できる属性の値は親要素から継承 inherit
  • marginborderのような継承されない属性の値は初期値に inital

という動作です。。。

HTML

<p>冴草きい</p>
<div class="yellow">
  <p>冴草きい</p>
  <p class="initial">OKOKOK~</p>
  <p class="inherit">ガンガンガンバ</p>
  <p class="unset">うしうしうっしー</p>
</div>

CSS

.yellow{
  color: #f1c847
  border: 1px solid #f1c847
}
.initial {color: initial; border: initial;}
.inherit {color: inherit; border: inherit;}
.unset {color: unset; border: unset;}

👇

See the Pen note. CSS unset simple by KIKIKI (@chaika-design) on CodePen.

inherit のものは親のborderも継承していますが、
unsetはもともと継承できない属性のborderは継承していません。

使い所があまり思いつきません…
all: initial; font-size: unset;みたいに併用して一部だけ継承させるとか?

まとめ

initial は初期化で inheritは親要素の継承って軽く考えていたのですが、思ったより深かったデス。。。


[参考]

Git ファイル名の大文字・小文字の変更が感知されないにハマる

Macのローカル環境だと画像のsrcで小文字でファイル名を指定していて、実際のファイルが大文字になってても表示されちゃったりするので、 うっかりPhotoshopとかでファイル名大文字にしてて大文字のまま画像書き出してコミットしちゃって、本番サーバーでpullしたら画像が表示されなくてミスに気づくなど…時々やってしまいます。

ファイル名をリネームしてコミットすればOKなのですが…
ファイル名の大文字を小文字を変更しただけでは、Gitに変更だと感知されない… だとぅ!?

どうやらGitのデフォルト設定ではファイル名の大文字/小文字を判別してないっぽい。(あれ? これってデフォルトの動作だったっけ…!?)

Gitでファイル名の大文字/小文字を識別させる方法

Gitでファイル名の大文字/小文字を識別させるには ignorecasefalseに設定すれば良いみたいです。

$ git config --global core.ignorecase false
$ git config --system core.ignorecase false

どんなプロジェクトでも識別しておいたほうが良いと思うのでglobalsystemに設定しちゃえば良いように思います。

Git の設定状態を確認

git config -l で設定を確認できる。
globalの設定を確認するには

$ git config --global -l

 
Gitがファイル名の大文字/小文字判別しないの昔もハマった様な記憶があって設定もしたような気がしてたんだけど… OSとかGitのアップデートとかなにかのタイミングで設定がリセットされた? 設定したの別のPCだったのかな… 記憶にない。

というより、ファイル名の大文字/小文字を判別するのはデフォルトにしておいて欲しい!
ファイル名を大文字にしちゃったミス気づきにくいので、Gitよ… なぜ ignorecase をデフォルトで true にした…


[参考]

わかばちゃんと学ぶ Git使い方入門〈GitHub、Bitbucket、SourceTree〉

わかばちゃんと学ぶ Git使い方入門〈GitHub、Bitbucket、SourceTree〉