fragmentary 2018-12-07T06:19:02+09:00 myakura Hatena::Blog hatenablog://blog/12704346814673868353 Microsoft EdgeのChromium移行とか hatenablog://entry/10257846132681419168 2018-12-07T06:19:02+09:00 2018-12-07T07:25:54+09:00 週明けに出回った、Microsoft EdgeがChromiumベースになるという話について、Microsoftからアナウンスがあった。 Microsoft Edge: Making the web better through more open source collaboration - Windows Experience Blog For the past few years, Microsoft has meaningfully increased participation in the open source software (OSS) community, becoming… <p>週明けに出回った、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft%20Edge">Microsoft Edge</a>が<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromium">Chromium</a>ベースになるという話について、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft">Microsoft</a>からアナウンスがあった。</p> <ul> <li><a href="https://blogs.windows.com/windowsexperience/2018/12/06/microsoft-edge-making-the-web-better-through-more-open-source-collaboration/">Microsoft Edge: Making the web better through more open source collaboration - Windows Experience Blog</a></li> </ul> <blockquote><p>For the past few years, <a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft">Microsoft</a> has meaningfully increased participation in the <a class="keyword" href="http://d.hatena.ne.jp/keyword/open%20source%20software">open source software</a> (<a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a>) community, becoming one of the world’s largest supporters of <a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a> projects. Today we’re announcing that we intend to adopt the <a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromium">Chromium</a> open source project in the development of <a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft%20Edge">Microsoft Edge</a> on the desktop to create better web compatibility for our customers and less fragmentation of the web for all web developers.</p></blockquote> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%F3">インターン</a>時代から10年近くも<a class="keyword" href="http://d.hatena.ne.jp/keyword/IE">IE</a>→Edgeに関わっていた<a href="https://twitter.com/jacobrossi/status/1021095510537408512">Jacob Rossiが夏にMicrosoftを抜けた</a>りもしていて、なにかあったのかなとは思っていたが。そういうことかーと、なんかえらく呆けてしまった。</p> <p>Edgeチームのお言葉も出た。</p> <ul> <li><a href="https://github.com/MicrosoftEdge/MSEdge">Microsoft Edge and Chromium Open Source: Our Intent</a></li> </ul> <p>なんと言えばいいかわからないが、言葉を出すならこれかな。苦い。</p> <h2>EdgeHTMLがなくなる</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>版に続き、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromium">Chromium</a>ベースになるEdgeは、これまでのエンジンEdgeHTMLを捨てることになる。<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>エンジンのChakraCoreについて詳細は語られていないが、<a href="https://github.com/Microsoft/ChakraCore/wiki/Roadmap#release-notes">半年近くセキュリティ関連の修正のみ</a>という現状を見るに、V8に移行するのではないか。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A6%A5%EB%A5%C8%A5%E9C">ウルトラC</a>で<a href="https://github.com/nodejs/node-chakracore">Node-Chakracore</a>みたく、shim使ってみたいなアプローチが……いや考えにくい。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromium">Chromium</a>移行の目的のひとつに、さらなる互換性の向上を挙げているからだ。</p> <blockquote><ol> <li>We will move to a <a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromium">Chromium</a>-compatible web platform for <a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft%20Edge">Microsoft Edge</a> on the desktop. Our intent is to align the <a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft%20Edge">Microsoft Edge</a> web platform simultaneously (a) with web standards and (b) with other <a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromium">Chromium</a>-based browsers. This will deliver improved compatibility for everyone and create a simpler test-matrix for web developers.</li> </ol> </blockquote> <p>なので<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>エンジンだけ<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chakra">Chakra</a>使うよなんて理由はとくにない。</p> <h2>開発者への影響</h2> <p>ひとつは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromium">Chromium</a>ベースになるので、とくにEdgeを気にすることがなくなる。リリーススケジュールを<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>とあわせるということはしないだろうから、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Opera">Opera</a>や<a class="keyword" href="http://d.hatena.ne.jp/keyword/Vivaldi">Vivaldi</a>みたくずれはあるかもしれないが、それなりにアップデートに追従するのではないか。</p> <p>ただ、Edgeを気にして開発していた人がどれくらいいたかを考えると、EdgeHTMLが減ったことで開発者が受ける影響は、プラスもマイナスもほとんどないのではないか。もともと<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromium">Chromium</a>との互換性を強く意識していたという触れ込みもあったし、またシェアも少ないので、どれくらい「Edge対応」があったのかというと、どうなんだろう。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft">Microsoft</a>にとっても、自分のとこの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>に引き込む強みも出せず、さらにケアされていないから、開発やメンテのコストが見合わないという状況になったのだろうし。</p> <p>なので「気にすること減るぜ!」といえる人、「嬉しい」を体感できる人って、どれくらいいるんだろうと(WebRTC絡みだといるのかな)。ぼくは気にしたことがほとんどなかったので、エンジンが減ることによる実作業への影響はとくにない。browser-compat-dataいじるときに調べる項目が減るくらいか。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/IE">IE</a>への影響</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromium">Chromium</a>ベースとなることで、OSのアップデートに紐付かない頻繁なアップデートが可能としている。さらに他のプラットフォーム版の展開も示唆されている。</p> <blockquote><ol> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft%20Edge">Microsoft Edge</a> will now be delivered and updated for all supported versions of <a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a> and on a more frequent cadence. We also expect this work to enable us to bring <a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft%20Edge">Microsoft Edge</a> to other platforms like <a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>.</li> </ol> </blockquote> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>版とな。そしてもっと読む。</p> <blockquote><p>Improving the web-platform experience for both end users and developers requires that the web platform and the browser be consistently available to as many devices as possible. To accomplish this, we will evolve the browser code more broadly, so that our distribution model offers an updated <a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft%20Edge">Microsoft Edge</a> experience + platform across all supported versions of <a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a>, while still maintaining the benefits of the browser’s close integration with <a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a>.</p></blockquote> <p>”distribution model offers an updated <a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft%20Edge">Microsoft Edge</a> experience + platform across all supported versions of <a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a>” とある。この"all supported versions of <a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a>"に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows%207">Windows 7</a>もカウントされるかだが、Edgeチームの話によると “We will evolve the <a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft%20Edge">Microsoft Edge</a> app architecture, enabling distribution to all supported versions of <a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a> including <a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows%207">Windows 7</a> and <a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows%208">Windows 8</a>, as well as <a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a> 10.” とのことで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows%207">Windows 7</a>版もくるようだ。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows%207">Windows 7</a>にはEdgeが提供されていないので、なのでIE11が減らないという話が一説にはあったが、出たとして、<a class="keyword" href="http://d.hatena.ne.jp/keyword/IE">IE</a>のシェアに影響はどれくらいあるのか。社内用の<a class="keyword" href="http://d.hatena.ne.jp/keyword/IE">IE</a>専用アプリケーションとか、<a class="keyword" href="http://d.hatena.ne.jp/keyword/IE">IE</a>以外はだめーというポリシーが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft">Microsoft</a>謹製アプリ(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromium">Chromium</a>ベース)の登場によって変わるのかどうか。</p> <h2>Edgeの意味</h2> <p>多プラットフォーム展開の意味はどれくらいあるかというと、使ってる<a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>/<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>/<a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>でお気に入りとかを共有したいときとかにはうれしそう。<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>版<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>があるのもそういう理由だろうし。</p> <p>とはいえそういう人はすでに<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>を使ってそうというのはある。ブラウザとかがそこまでわかるわけでもこだわるわけでもない人、たとえばうちの母とか、そういう人にはいいかもしれない。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>ベースになるからEdgeのユーザーが増えるかというと、うーんどうなのだろう。でもEdgeはそんなに機能が多いわけでもなかった(控えめな表現)ので、機能が増えたよーこれならEdgeでいいかーという人がいる…か……も……?</p> <h2>ウェブプラットフォームへの影響</h2> <p>大きいのかどうなのか。大きいのだろうけど、正直わからなくなった。</p> <p>独立した<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%F3%A5%C0%A5%EA%A5%F3%A5%B0">レンダリング</a>エンジンがまた一つ減って、現在はBlink, <a class="keyword" href="http://d.hatena.ne.jp/keyword/Gecko">Gecko</a>, <a class="keyword" href="http://d.hatena.ne.jp/keyword/WebCore">WebCore</a>になる(<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>エンジンはちょっとおいておく)。Blinkの過去を考えると、機能によってはBlinkと<a class="keyword" href="http://d.hatena.ne.jp/keyword/WebCore">WebCore</a>を分けられないこともあるだろう。</p> <p>なので、複数のエンジンでの実装をもって標準を作るという、Web関連の標準化団体がいまやっているポリシーを貫くのがとてもつらくなる。</p> <p>Edgeがどれくらいエンジンの多様性に寄与していたかどうかはわからない。テストケースに通るための頭数にはなったかもしれない。Tridentから引き継いだ、あまり詳細になってない仕様の互換性については、改善したかもしれないが。新しい仕様についてはどうなのだろうね。</p> <p>これはウェブプラットフォームのある種の選択でもあるのかなとも思う。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3">プラグイン</a>という機能追加を断ったため、ブラウザ上でいろいろ賄おうと自身をふくれさせ、結果新規参入ができなくなってしまった。</p> <h2>標準化と<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a></h2> <p>エンジンの多様性はともかく、標準化においてはどうなるだろう。新しい機能については、最近はWICGで小さな機能を検討するというのが大体の流れだけれど、提案はもっぱら<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>チームの人で、またAMP絡みと思われる案件から生まれた機能が多い。WICGでのドラフトもちゃんと進んでいればいいのだけれど、コメントが付くのが<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>でのIntent to Ship段階が多いような印象にある。仕様が<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>のリリーススケジュールに、不用意に影響されているような気がする。</p> <p>Edgeチームが<a href="https://github.com/MicrosoftEdge/MSEdge#contribution-initial-areas-of-focus">Chromiumにおいてまずフォーカスしたいと考えているもの</a>のうち、プラットフォーム周りでの貢献がありそうなのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%AF%A5%BB%A5%B7%A5%D3%A5%EA%A5%C6%A5%A3">アクセシビリティ</a>と新しめの入力とのこと。そういうところでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>チームと導入時にいろいろ議論してくれるのかもしれないが、他のところでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>というか<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>に傾いたプラットフォーム拡張化が不安である。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Microsoft">Microsoft</a>はブログの中で、”move to a <a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromium">Chromium</a>-compatible web platform” と書いていた。言い方ではあるんだけれど、こうは書いてほしくなかったな。あとは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a>への貢献をうたってはいるが、オープンなプラットフォームへの貢献については言及していないのも悲しい(Edgeチームのノートにフォローはあるけれど)。</p> <h2>作る人がブラウザ自体を忘れないか</h2> <p>もうすでに起こっていることではあると思うのだけど、自分の使っている環境以外を想定しないどころか、想定できなくなるのかなあと。</p> <p>想定しないのは、ちらほら増えてきた「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>でしか動きません」というやつ。自分の社内ツールにもひとつ「どうせみんな<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>使うから」というところで<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>じゃ動かないのがあって切ない。意図的に他のエンジンを無視しているというのではなく、Dynamic importに依存しているからなので、まあなあ…というものではある。</p> <p>でも、標準自体が固いものではなく、変わるものであり、さらに各々がばらばらに実装するというウェブにおいては、「標準に入るから」を理由にするのも、もちろん嬉しくはない。そういう、作る前の判断から、蔑ろにされるのは危ないなあと。</p> <p>で、想定できなくなるというのは、ええと。これはブラウザの話ではないけど、先日会社のサイトをいろいろいじってた際に、自分のマシンだけ画像が表示されなくなるという現象に出くわした。いろいろ原因を調べたら、picture要素の書き方をちょっとミスって、1xな環境時のURLがおかしくなっていたというものだった。</p> <p>なぜそれに気がついたかというと、ぼく一人だけがnon-<a class="keyword" href="http://d.hatena.ne.jp/keyword/Retina">Retina</a>な<a class="keyword" href="http://d.hatena.ne.jp/keyword/Mac">Mac</a>を使っていたのだった。他はみんな年代は違えど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Retina%A5%C7%A5%A3%A5%B9%A5%D7%A5%EC%A5%A4">Retinaディスプレイ</a>な<a class="keyword" href="http://d.hatena.ne.jp/keyword/Mac">Mac</a>であったという。ちゃんとテストをしろよという話なのかもしれないが、テスト対象の選定ですでに外れてしまっていたら?それがわからなくなっていたら?</p> <p>環境がなにかに偏っていると、それ以外を見るのがとてもむつかしくなる。そして最後には、その偏り自体も認識できなくなってしまう。さっき「他のプラットフォームでEdge出てうれしいかなあ」みたいに書いたけど、ぼくももう、見えなくなっているのかもしれない。それも、エンジンというレベルではなくて、ブラウザというレベルで。同じエンジンなら、使う人の好みやニーズに合わせていっぱいあってもいいはずなのにね。</p> <p>いろんなことを考えられるというのは、豊かなことだと思っているし、そうであってほしい。ただそれは豊かすぎて、みんな忙しくなってしまってるような今では暴力くらいになってしまってるのかもしれない。</p> myakura SafariのUA文字列が固定されて固定されなくなったおはなし hatenablog://entry/17391345971635479648 2018-04-16T08:30:00+09:00 2018-04-17T02:09:20+09:00 Safari 11.1の開発中に一瞬UA文字列が固定されたのだけど、リリース前に固定されなくなったのだった。 <p>Jxckが以前、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a>文字列が固定されたというのを書いていた。</p> <ul> <li><a href="https://blog.jxck.io/entries/2018-01-17/freezing-user-agent-string.html">Safari による User-Agent 固定化と Web における Feature Detection | blog.jxck.io</a></li> </ul> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a> Technology <a class="keyword" href="http://d.hatena.ne.jp/keyword/Preview">Preview</a> 46で入った変更だ。</p> <ul> <li><a href="https://webkit.org/blog/8042/release-notes-for-safari-technology-preview-46/">Release Notes for Safari Technology Preview 46 | WebKit</a></li> </ul> <blockquote><p>Froze the user-agent string to reduce web compatibility risk and to prevent its use for fingerprinting</p></blockquote> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>でも<a class="keyword" href="http://d.hatena.ne.jp/keyword/Apple">Apple</a>の<a href="https://twitter.com/rmondello/status/943545865204989953">Ricky Mondelloがそれを伝えていて</a>、ちょっと騒ぎになっていた。「それは困る」的な反応が結構多かったのと、中には「やっぱり<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>は新たなIE6だ」みたいな、リスペクトのない反応もちらほら。なんだかね……</p> <hr /> <p>さて、これだけだったらここで書くことはなにもないんだけど、続きがある。その後この固定化はとりやめられたのだった。</p> <p>現在は<a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a>文字列に含まれていたOSのバージョンが固定されず、ちゃんと実際のバージョンを反映するようになっている。先日リリースされた<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a> 11.1でも<a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a>文字列の変更については述べているものの、固定という表現ではなくなった。</p> <ul> <li><a href="https://developer.apple.com/library/content/releasenotes/General/WhatsNewInSafari/Articles/Safari_11_1.html">What's New in Safari 11.1</a></li> </ul> <blockquote><p>Updated the User-Agent String Policy</p> <ul> <li>Changed the updating policy to to only continue updating the OS version number and <a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a> version number.</li> </ul> </blockquote> <p>参考までに、手元の<a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a> 10.13.4で確認した、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a> 11.1の<a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a>文字列を。</p> <pre class="code" data-lang="" data-unlink>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15 </pre> <p>以下は<a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a>文字列固定の経緯と、再度変更されるまでの流れ。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a>文字列の固定とはなんだったのか</h2> <p>RickyのツイートやSTP 46のリリースノートだけだと詳細がわからないが、ちゃんとコミットがある。</p> <ul> <li><a href="https://trac.webkit.org/changeset/225562/webkit">Changeset 225562 – WebKit — Limit user agent versioning to an upper bound</a></li> </ul> <blockquote><p>Freeze the version reported as User Agent to OS 10.13.4 (OS 11.3 on <a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>) and <a class="keyword" href="http://d.hatena.ne.jp/keyword/WebKit">WebKit</a> 605.1.15 for User Agent purposes.</p></blockquote> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>のバージョンが10.13(High <a class="keyword" href="http://d.hatena.ne.jp/keyword/Sierra">Sierra</a>)以降の場合は<code>10_13_4</code>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>の場合は<code>11_3</code>になると。ついでに<a class="keyword" href="http://d.hatena.ne.jp/keyword/WebKit">WebKit</a>のバージョンも<code>605.1.15</code>に固定される。</p> <p>なので、パッチが入ったSTP 46<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%AB%A4%E9%A4%B7">からし</a>ばらくは、以下のようになっていた。</p> <pre class="code" data-lang="" data-unlink>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15</pre> <p>STP 46の時点では<a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>は10.13.3なので、たしかにOSのバージョンが固定されている感じなのがわかる。</p> <h3>変更の理由</h3> <p>STPのリリースノートにもフィンガープリンティングを避けるという目的が書いてあったけど、該当バグにもう少し細かく書かれていた。</p> <ul> <li><a href="https://bugs.webkit.org/show_bug.cgi?id=180365">180365 – Limit user agent versioning to an upper bound</a></li> </ul> <blockquote><p>Stop reporting more recent user agent version strings, freezing the version at a specific moment in time. We should do this for a number of reasons:</p> <p>(1) User Agent <a class="keyword" href="http://d.hatena.ne.jp/keyword/sniffing">sniffing</a> is a terrible way to determine whether a browser supports certain features.</p> <p>(2) Bad User Agent <a class="keyword" href="http://d.hatena.ne.jp/keyword/sniffing">sniffing</a> code on the web create compatibility problems every time we update the versions.</p> <p>(3) Overly-specific version information provides useful fingerprinting data while providing almost no user benefit.</p></blockquote> <ol> <li>ある機能のサポート状況をチェックする方法としてひどい</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a>文字列検出のコードがひどいと互換性の問題にバージョンを上げるたびに毎回出くわす</li> <li>細かすぎるバージョンの情報はフィンガープリンティングにつながる危険性がある</li> </ol> <p>フィンガープリンティングだけではなくて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a>文字列について一般的に問題とされていることも理由となっていた。</p> <h2>OSのバージョン固定がなくなった</h2> <p>Rickyのツイートにもたくさんの「困る」という声があったし、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Apple">Apple</a>にそのような声が寄せられたか、はたまた互換性のバグに引っかかったのかわからないけど、件のコミットから2ヶ月ほど経った今年2月、方針が転換されるコミットが入った。</p> <ul> <li><a href="https://trac.webkit.org/changeset/228334/webkit">Changeset 228334 – WebKit — [macOS, iOS] Expose OS marketing version in UserAgent</a></li> </ul> <blockquote><p>Revert back to dynamically reading the operating system marketing version rather than using a hard-coded version.</p></blockquote> <p>OSのバージョンをシステムから読むように(再度)変更したと。つまりは固定されなくなった。</p> <p>いったん固定するとした方針を軟化させるにあたっては、バグに議論があった。</p> <ul> <li><a href="https://bugs.webkit.org/show_bug.cgi?id=182629">182629 – [macOS, iOS] Expose OS marketing version in UserAgent</a></li> </ul> <p>まずは固定をやめる理由について。</p> <blockquote><p>The primary reasons were:</p> <ol> <li><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/WebKit">WebKit</a> sometimes <a class="keyword" href="http://d.hatena.ne.jp/keyword/ships">ships</a> with bugs that can be worked around at the website level. Having a release version allows websites to activate workarounds where needed.</p></li> <li><p>Decisions about what site content to send to a user agent are often made before the page is loaded. Having <a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a> information when connecting to the server allows websites to send only the relevant payload (e.g., more recent <a class="keyword" href="http://d.hatena.ne.jp/keyword/javascript">javascript</a>, more efficient image formats, etc.)</p></li> <li><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a> (for example) <a class="keyword" href="http://d.hatena.ne.jp/keyword/ships">ships</a> with the same version on several operating system revisions. Sometimes bugs exist in specific OS revisions that websites can work around.</p></li> </ol> <p>For these reasons, we decided to relax some of the restrictions we had originally planned on making.</p></blockquote> <ol> <li>バグがある状態でリリースされてしまうと、ウェブサイトで対応するしかない。リリースバージョンを含めるを含めることで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EF%A1%BC%A5%AF%A5%A2%A5%E9%A5%A6%A5%F3%A5%C9">ワークアラウンド</a>が可能になる</li> <li>ブラウザごとにコンテンツを出し分けるサーバーサイドのコードがあって、<a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a>文字列を含めることで必要なものだけを送れる</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>はOSといっしょにアップデートされるけど、OSにバグがあるときの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EF%A1%BC%A5%AF%A5%A2%A5%E9%A5%A6%A5%F3%A5%C9">ワークアラウンド</a>に使える</li> </ol> <p>といった感じ。1、2についてはどのブラウザにも言えるだろうけど、3については半年に一度のリリースで、かつOSとくっついている<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>ならではの事情が大きそうだ。</p> <p>一旦は決めた固定をやめること、そしてその理由については、それはどうなんだという反発もあった。mitz氏はこう問うている。</p> <blockquote><p>Shouldn’t <a class="keyword" href="http://d.hatena.ne.jp/keyword/WebKit">WebKit</a> provide a direct and explicit way for websites to determine that a bug is fixed?</p></blockquote> <p>バグが直ったら伝える仕組みを設けるべきではという。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%AD%A5%E5%A5%E1%A5%F3%A5%C6%A1%BC%A5%B7%A5%E7%A5%F3">ドキュメンテーション</a>よりも直接的なものを想定しているのかな。とはいえ、だいぶ理想を見ているようにも見える。そういうのがあってうまく機能したなら、世の中は<a class="keyword" href="http://d.hatena.ne.jp/keyword/XML">XML</a>ベースになっていたんじゃないかな。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a>文字列という手段を使い続けることについても、別の方法がないのかという疑問も提示している。</p> <blockquote><p>Aren’t there other request headers dedicated to explicitly, directly conveying what the user agent supports?</p></blockquote> <p>Client Hintsみたいなものの機能版という感じかな。ヘッダではないけど<code>hasFeature()</code>というものがあって、これはなかなか残念な結果だったはずなので、ヘッダにあってもあまりうまく機能しない気がする。「サポートしている」の粒度が人によってそれぞれ違うだろうから、うまく満たせる仕組みはつくれないだろう。</p> <p>とまあ、疑問が投げられたけど結局コミットされたので、使える<a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a>文字列が復活した。めでたいのか、めでたくないのか。</p> <hr /> <p>なお、OSのバージョンは固定されなくなったが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/WebKit">WebKit</a>のバージョンは<code>605.1.15</code>に固定されたままだ。<a class="keyword" href="http://d.hatena.ne.jp/keyword/WebKit">WebKit</a>のバージョンでなにかしたいケースってあるかな……ほしいのはOSバージョンだろうから、こいつはそこまで気にされないかなーと思う。</p> <h2>おまけ:なんでアンダースコアで区切ってるのか</h2> <p>OSのバージョンはなぜだか<code>10_13_4</code>と、アンダースコア区切りになっている。</p> <p>なんかあったのかなーと思ったら、UserAgentCocoa.mmというファイルにこんなコメントが書いてあった。</p> <pre class="code" data-lang="" data-unlink>// Use underscores instead of dots because when we first added the Mac OS X version to the user agent string // we were concerned about old DHTML libraries interpreting &#34;4.&#34; as Netscape 4. That&#39;s no longer a concern for us // but we&#39;re sticking with the underscores for compatibility with the format used by older versions of Safari.</pre> <p>OSのバージョンを<a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a>文字列にぶっこんだときに、<code>4.</code>という文字列が現れたら問答無用で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Netscape">Netscape</a> 4と認識するDHTMLライブラリに出会ったらしくそれを迂回する目的だったらしい。たしかに<a class="keyword" href="http://d.hatena.ne.jp/keyword/Netscape">Netscape</a> Communicator時代は4.0とか4.5とか4.7とかマイナーバージョンが更新されたから、<code>4.</code>でマッチさせるようにしたのかな。たしかに<a class="keyword" href="http://d.hatena.ne.jp/keyword/Netscape">Netscape</a>はいまと比べて<a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a>文字列だいぶ短かったし。</p> <p>うーんでも、<code>4.</code>でマッチするなら<a class="keyword" href="http://d.hatena.ne.jp/keyword/IE">IE</a>もマッチする気がするんだけどな……</p> <p>コミットを探したらあった。</p> <ul> <li><a href="https://trac.webkit.org/changeset/28499/webkit">Changeset 28499 – WebKit</a></li> </ul> <blockquote><p>Added <a class="keyword" href="http://d.hatena.ne.jp/keyword/Mac%20OS%20X">Mac OS X</a> version string, right after the string "<a class="keyword" href="http://d.hatena.ne.jp/keyword/Mac%20OS%20X">Mac OS X</a>", but with underscores instead of dots to avoid the dreaded "4." problem (old libraries that think a "4." anywhere in the user agent means <a class="keyword" href="http://d.hatena.ne.jp/keyword/Netscape">Netscape</a> 4).</p></blockquote> <p><q>No way to detect <a class="keyword" href="http://d.hatena.ne.jp/keyword/Tiger">Tiger</a> vs <a class="keyword" href="http://d.hatena.ne.jp/keyword/Leopard">Leopard</a> from <a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>'s user agent string</q>と、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Tiger">Tiger</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/Leopard">Leopard</a>を判別したいなにかがあったらしい。なのでOSのバージョンを入れたのだけど、<code>4.</code>が問題になった過去の問題をふまえてアンダースコアにしたと。</p> <p>ではその<code>4.</code>についての言及はどれかなーとさらに探したら、これまたあった。ちゃんと<a class="keyword" href="http://d.hatena.ne.jp/keyword/changelog">changelog</a>書いてるのすごいなー</p> <ul> <li><a href="https://trac.webkit.org/changeset/20755/webkit">Changeset 20755 – WebKit</a></li> </ul> <blockquote><p>Adds a build phase script that ensures <a class="keyword" href="http://d.hatena.ne.jp/keyword/WebKit">WebKit</a>'s version dosen't end in a 4. If our version ends in 4, some sites might think we are <a class="keyword" href="http://d.hatena.ne.jp/keyword/Netscape">Netscape</a> 4 in their user agent checks.</p></blockquote> <p>これを読むと<code>4.</code>ではなく<code>4</code>な気がするんだけど、いつのまにか<code>4.</code>になってるのはどうしてなんだろう。もうわかることはないんだろうけど。</p> <p>元のコメントを読むと、現在はドットにしたところで互換性の問題はないらしいが、逆に過去の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>との互換性がとれなくなるという話でアンダースコアが残されているらしい。ふしぎなコードとバグと互換性でウェブは続いていく。</p> myakura Chromeでボタンをクリックしたときのフォーカスリング hatenablog://entry/17391345971633483406 2018-04-09T08:30:00+09:00 2018-04-16T01:32:39+09:00 geckotangが「Chromeでボタンをマウスでクリックしたときにフォーカスリングが出たり出なかったりするのなんで」と言っていて、なんかお前調べろよ的な感じだったので調べることにした。 使うのはcs.chromium.org。<button>なので"HTMLButtonElement"で検索して、それっぽいファイルを探す。あった。 html_button_element.h "focus"で検索するとSupportsAutoFocus()というメソッドが見つかる……がこれはautofocus属性の対象になるかとかそういう感じがするのでこれではない。というかそっか、autofocus指定でき… <p><a href="https://twitter.com/geckotang">geckotang</a>が「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>でボタンをマウスでクリックしたときにフォーカスリングが出たり出なかったりするのなんで」と言っていて、なんかお前調べろよ的な感じだったので調べることにした。</p> <p>使うのは<a href="https://cs.chromium.org/">cs.chromium.org</a>。<code>&lt;button&gt;</code>なので"HTMLButtonElement"で検索して、それっぽいファイルを探す。あった。</p> <ul> <li><a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/html/forms/html_button_element.h">html_button_element.h</a></li> </ul> <p>"focus"で検索すると<a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/html/forms/html_button_element.h?rcl=796a0e014bc3985709c0a35538d606ef1da31e1b&amp;l=67"><code>SupportsAutoFocus()</code></a>というメソッドが見つかる……がこれは<code>autofocus</code>属性の対象になるかとかそういう感じがするのでこれではない。というかそっか、<code>autofocus</code>指定できるんだ……<code>&lt;input&gt;</code>にしか使ったことなかったからなんか使えないって思ってしまってた。</p> <p><code>HTMLButtonElement</code>にはなさそうなので、参照している<code>HTMLFormControlElement</code>を見る。</p> <ul> <li><a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/html/forms/html_form_control_element.h">html_form_control_element.h</a></li> </ul> <p>"focus"で検索……<a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/html/forms/html_form_control_element.h?rcl=796a0e014bc3985709c0a35538d606ef1da31e1b&amp;l=125"><code>ShouldShowFocusRingOnMouseFocus()</code></a>とか<a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/html/forms/html_form_control_element.h?rcl=796a0e014bc3985709c0a35538d606ef1da31e1b&amp;l=161"><code>ShouldHaveFocusAppearance()</code></a>とか、それっぽいのがある!</p> <p>メソッドを選択して、Call Hierarchyを見てみる。<a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/layout_theme.cc">layout_theme.cc</a>に<code>ShouldDrawDefaultFocusRing()</code>というメソッドが見える。これかーーーー!?</p> <h2>フォーカスリングが出る条件</h2> <p><a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/layout_theme.cc?rcl=796a0e014bc3985709c0a35538d606ef1da31e1b&amp;l=404-417"><code>ShouldDrawDefaultFocusRing()</code></a>はこうなっていた。</p> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synType">bool</span> LayoutTheme::ShouldDrawDefaultFocusRing(<span class="synType">const</span> Node* node, <span class="synType">const</span> ComputedStyle&amp; style) <span class="synType">const</span> { <span class="synStatement">if</span> (ThemeDrawsFocusRing(style)) <span class="synStatement">return</span> <span class="synConstant">false</span>; <span class="synStatement">if</span> (!node) <span class="synStatement">return</span> <span class="synConstant">true</span>; <span class="synStatement">if</span> (!style.HasAppearance() &amp;&amp; !node-&gt;IsLink()) <span class="synStatement">return</span> <span class="synConstant">true</span>; <span class="synComment">// We can't use LayoutTheme::isFocused because outline:auto might be</span> <span class="synComment">// specified to non-:focus rulesets.</span> <span class="synStatement">if</span> (node-&gt;IsFocused() &amp;&amp; !node-&gt;ShouldHaveFocusAppearance()) <span class="synStatement">return</span> <span class="synConstant">false</span>; <span class="synStatement">return</span> <span class="synConstant">true</span>; } </pre> <p>if文を読み解く。</p> <ol> <li>テーマがフォーカスリングを出す → <code>false</code></li> <li>ノードじゃない → <code>true</code></li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D4%A5%A2%A5%E9%A5%F3%A5%B9">アピアランス</a>ががない、かつリンクでない → <code>true</code></li> <li>フォーカスされている、かつフォーカスを表示すべきじゃないと判断してる → <code>false</code></li> </ol> <p>ふんふん(わかってない)</p> <h3>テーマのフォーカスリング</h3> <p>テーマがフォーカスリングを出すのかは、<code>ThemeDrawsFocusRing()</code>を見ればいいらしい。メソッドをクリックすると<a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/layout_theme.h">layout_theme.h</a>に飛んだ。</p> <ul> <li><a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/layout_theme.h?rcl=7cb8a1b7ac34d6c251eac7aa3c4c1f983adc7a00&amp;l=254"><code>ThemeDrawsFocusRing()</code></a></li> </ul> <pre class="code lang-cpp" data-lang="cpp" data-unlink> <span class="synType">virtual</span> <span class="synType">bool</span> ThemeDrawsFocusRing(<span class="synType">const</span> ComputedStyle&amp;) <span class="synType">const</span> = <span class="synConstant">0</span>; </pre> <p>さらにクリック。<a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/layout_theme_default.cc">layout_theme_default.cc</a>なるものに飛ぶ。</p> <ul> <li><a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/layout_theme_default.cc?rcl=7cb8a1b7ac34d6c251eac7aa3c4c1f983adc7a00&amp;l=64-74"><code>LayoutThemeDefault::ThemeDrawsFocusRing()</code></a></li> </ul> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synType">bool</span> LayoutThemeDefault::ThemeDrawsFocusRing(<span class="synType">const</span> ComputedStyle&amp; style) <span class="synType">const</span> { <span class="synStatement">if</span> (UseMockTheme()) { <span class="synComment">// Don't use focus rings for buttons when mocking controls.</span> <span class="synStatement">return</span> style.Appearance() == kButtonPart || style.Appearance() == kPushButtonPart || style.Appearance() == kSquareButtonPart; } <span class="synComment">// This causes Blink to draw the focus rings for us.</span> <span class="synStatement">return</span> <span class="synConstant">false</span>; } </pre> <p>基本的には<code>false</code>らしい。<code>true</code>になりそうなのもテストで使う系なのかな。</p> <p>プラットフォームによって上書きされてるかもしれないなーと思ったけど、layout_theme.ccの上の方に<q>The methods in this file are shared by all themes on every platform.</q>なんてコメントがあった。しかしこのメソッド、テスト以外になにか使い所あるのかなあ。</p> <h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D4%A5%A2%A5%E9%A5%F3%A5%B9">アピアランス</a>があるかないか</h3> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D4%A5%A2%A5%E9%A5%F3%A5%B9">アピアランス</a>がない、というのは<code>-webkit-appearance</code>プロパティの話らしい。<a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/style/computed_style.h">computed_style.h</a>に<a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/style/computed_style.h?rcl=7cb8a1b7ac34d6c251eac7aa3c4c1f983adc7a00&amp;l=2194-2195"><code>HasAppearance()</code></a>が定義されていた。</p> <pre class="code lang-cpp" data-lang="cpp" data-unlink> <span class="synComment">// -webkit-appearance utility functions.</span> <span class="synType">bool</span> HasAppearance() <span class="synType">const</span> { <span class="synStatement">return</span> Appearance() != kNoControlPart; } </pre> <p><code>kNoControlPart</code>とは、theme_types.hの<a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/theme_types.h?rcl=796a0e014bc3985709c0a35538d606ef1da31e1b&amp;l=49"><code>ControlPart</code>というenumに定義されていた</a>。<code>-webkit-appearance: none</code>に相当する定数っぽい。</p> <p>CSSProperties.json5(<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>プロパティの定義を生成するもとのファイル)を見ると、<a href="https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/core/css/CSSProperties.json5#3089"><code>-webkit-appearance</code>の初期値が<code>kNoControlPart</code>と定義されてた</a>ので、認識はあってそう。</p> <h3>フォーカスを見せるのか</h3> <p>フォーカスすべきでないという判断は、<code>ShouldHaveFocusAppearance()</code>を見ればいい。クリックしたら<a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/html/forms/html_form_control_element.cc">html_form_control_element.cc</a>に定義されていた。</p> <ul> <li><a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/html/forms/html_form_control_element.cc?rcl=7cb8a1b7ac34d6c251eac7aa3c4c1f983adc7a00&amp;l=410-412"><code>HTMLFormControlElement::ShouldHaveFocusAppearance()</code></a></li> </ul> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synType">bool</span> HTMLFormControlElement::ShouldHaveFocusAppearance() <span class="synType">const</span> { <span class="synStatement">return</span> !was_focused_by_mouse_ || ShouldShowFocusRingOnMouseFocus(); } </pre> <p><a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/html/forms/html_form_control_element.cc?rcl=7cb8a1b7ac34d6c251eac7aa3c4c1f983adc7a00&amp;l=406-408"><code>ShouldShowFocusRingOnMouseFocus()</code>はすぐ上にあった</a>。</p> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synType">bool</span> HTMLFormControlElement::ShouldShowFocusRingOnMouseFocus() <span class="synType">const</span> { <span class="synStatement">return</span> <span class="synConstant">false</span>; } </pre> <p>マウスでフォーカスされていない場合にのみ、フォーカスすべきという話らしい。</p> <hr /> <p>以上をふまえると、基本的にbutton要素は以下の場合にフォーカスリングを出すらしい。</p> <ul> <li><code>-webkit-appearance</code>がない場合</li> <li>マウス以外でフォーカスした場合</li> </ul> <p>なので、通常のボタンをマウスでクリックした場合はフォーカスリング出ない。</p> <h2>appearanceプロパティのcomputed styleが変わるとき</h2> <p>geckotangによると<code>border</code>やら<code>background-color</code>などを指定すると、マウスクリック時にもフォーカスリングが出るとのこと。</p> <p>先程の<code>ShouldDrawDefaultFocusRing()</code>が<code>true</code>になる条件をふまえると、<code>-webkit-appearance</code>がない場合にフォーカスリングが出るということなので、<code>-webkit-appearance</code>が変わる条件を探せばよい。</p> <p>さてどうしたもんかなーと思っていたのだけど、layout_theme.ccの上の方に<a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/layout_theme.cc?rcl=1e287a26dad8bc0264b852e609644fd898b81aca&amp;l=85-114">こんなコード</a>があった。</p> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synType">void</span> LayoutTheme::AdjustStyle(ComputedStyle&amp; style, Element* e) { DCHECK(style.HasAppearance()); ControlPart part = style.Appearance(); <span class="synComment">// ...</span> <span class="synStatement">if</span> (IsControlStyled(style)) { <span class="synStatement">if</span> (part == kMenulistPart) { style.SetAppearance(kMenulistButtonPart); part = kMenulistButtonPart; } <span class="synStatement">else</span> { style.SetAppearance(kNoControlPart); <span class="synStatement">return</span>; } } <span class="synComment">// ...</span> } </pre> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D4%A5%A2%A5%E9%A5%F3%A5%B9">アピアランス</a>を見て、特定の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D4%A5%A2%A5%E9%A5%F3%A5%B9">アピアランス</a>でない場合は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D4%A5%A2%A5%E9%A5%F3%A5%B9">アピアランス</a>を変更するというコード。</p> <p>これどこで使われるのかなーと思ったのだけど、<a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/layout_theme.h?l=78-85">layout_theme.hに関数の説明が書いてあった</a>。</p> <pre class="code" data-lang="" data-unlink> // This method is called whenever style has been computed for an element and // the appearance property has been set to a value other than &#34;none&#34;. // The theme should map in all of the appropriate metrics and defaults given // the contents of the style. This includes sophisticated operations like // selection of control size based off the font, the disabling of appearance // when certain other properties like &#34;border&#34; are set, or if the appearance // is not supported by the theme. void AdjustStyle(ComputedStyle&amp;, Element*);</pre> <p>スタイルが計算された、もしくは<code>appearance</code>が<code>none</code>以外になったときにコールされると。おっけ。これだ。</p> <h3>どんなときに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D4%A5%A2%A5%E9%A5%F3%A5%B9">アピアランス</a>が変わるのか</h3> <p>もっかいさっきのコードを。</p> <pre class="code lang-cpp" data-lang="cpp" data-unlink> <span class="synStatement">if</span> (IsControlStyled(style)) { <span class="synStatement">if</span> (part == kMenulistPart) { style.SetAppearance(kMenulistButtonPart); part = kMenulistButtonPart; } <span class="synStatement">else</span> { style.SetAppearance(kNoControlPart); <span class="synStatement">return</span>; } } </pre> <p><code>IsControlStyled</code>という状態の場合でかつ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D4%A5%A2%A5%E9%A5%F3%A5%B9">アピアランス</a>がメニューリストでないものは<code>kNoControlPart</code>に切り替えるらしい。</p> <p><a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/layout_theme.cc?rcl=1e287a26dad8bc0264b852e609644fd898b81aca&amp;l=374-392"><code>IsControlStyled()</code>の定義</a>を見てみる。</p> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synType">bool</span> LayoutTheme::IsControlStyled(<span class="synType">const</span> ComputedStyle&amp; style) <span class="synType">const</span> { <span class="synStatement">switch</span> (style.Appearance()) { <span class="synStatement">case</span> kPushButtonPart: <span class="synStatement">case</span> kSquareButtonPart: <span class="synStatement">case</span> kButtonPart: <span class="synStatement">case</span> kProgressBarPart: <span class="synStatement">return</span> style.HasAuthorBackground() || style.HasAuthorBorder(); <span class="synStatement">case</span> kMenulistPart: <span class="synStatement">case</span> kSearchFieldPart: <span class="synStatement">case</span> kTextAreaPart: <span class="synStatement">case</span> kTextFieldPart: <span class="synStatement">return</span> style.HasAuthorBackground() || style.HasAuthorBorder() || style.BoxShadow(); <span class="synStatement">default</span>: <span class="synStatement">return</span> <span class="synConstant">false</span>; } } </pre> <p><code>&lt;button&gt;</code>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D4%A5%A2%A5%E9%A5%F3%A5%B9">アピアランス</a>は<code>kButtonPart</code>なので、<code>style.HasAuthorBackground() || style.HasAuthorBorder()</code>を満たす場合、そのコン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%ED%A1%BC%A5%EB">トロール</a>にはスタイルがついていると認識される。</p> <p><a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/css/resolver/style_resolver.cc?rcl=ba8e64a93bf1396983c99c1ac08c23c08951cae0&amp;l=1920-1935"><code>HasAuthorBackground()</code>の定義</a>を見てみる。</p> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synType">bool</span> StyleResolver::HasAuthorBackground(<span class="synType">const</span> StyleResolverState&amp; state) { <span class="synType">const</span> CachedUAStyle* cached_ua_style = state.GetCachedUAStyle(); <span class="synStatement">if</span> (!cached_ua_style) <span class="synStatement">return</span> <span class="synConstant">false</span>; FillLayer old_fill = cached_ua_style-&gt;background_layers; FillLayer new_fill = state.Style()-&gt;BackgroundLayers(); <span class="synComment">// Exclude background-repeat from comparison by resetting it.</span> old_fill.SetRepeatX(EFillRepeat::kNoRepeatFill); old_fill.SetRepeatY(EFillRepeat::kNoRepeatFill); new_fill.SetRepeatX(EFillRepeat::kNoRepeatFill); new_fill.SetRepeatY(EFillRepeat::kNoRepeatFill); <span class="synStatement">return</span> (old_fill != new_fill || cached_ua_style-&gt;background_color != state.Style()-&gt;BackgroundColor()); } </pre> <p>だるくなってきたので深く追ってないけど、<code>background-repeat</code>以外のbackground関連プロパティが変わってたら指定されてるという判断なのかな。</p> <p>続いて<a href="https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/css/resolver/style_resolver.cc?rcl=ba8e64a93bf1396983c99c1ac08c23c08951cae0&amp;l=1937-1945"><code>HasAuthorBorder()</code></a>。</p> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synType">bool</span> StyleResolver::HasAuthorBorder(<span class="synType">const</span> StyleResolverState&amp; state) { <span class="synType">const</span> CachedUAStyle* cached_ua_style = state.GetCachedUAStyle(); <span class="synStatement">return</span> cached_ua_style &amp;&amp; (cached_ua_style-&gt;border_image != state.Style()-&gt;BorderImage() || !cached_ua_style-&gt;BorderColorEquals(*state.Style()) || !cached_ua_style-&gt;BorderWidthEquals(*state.Style()) || !cached_ua_style-&gt;BorderRadiiEquals(*state.Style()) || !cached_ua_style-&gt;BorderStyleEquals(*state.Style())); } </pre> <p>border関連が変わってたらだめと。</p> <hr /> <p>なので、背景とborder関連プロパティ(<code>border-image</code>, <code>border-radius</code>含む)が変更されたら、そのコン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%ED%A1%BC%A5%EB">トロール</a>にスタイルがあたってると認識され、マウスクリック時でもフォーカスリングが当たるようになる。</p> <h2>フォーカスリングを出したくない?</h2> <p>出したくない場合、borderとbackground関連のプロパティは使えない……ちょっと現実的でない。とはいえ<code>:focus { outline: 0 }</code>はダメゼッタイ。ジレンマ。</p> <p>というわけで<a href="https://drafts.csswg.org/selectors/#the-focus-visible-pseudo"><code>:focus-visible</code></a>なんて擬似クラスができた。<a href="https://www.chromestatus.com/features/5823526732824576">Chromeで実装中</a>なのでもうちょいでよさげな感じになる。</p> <p>そういえば、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>以外でマウスクリック時にフォーカスリングを出すブラウザってあったっけ…?<a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>だと<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>は出さないみたいだけど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a>や<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>とかはどうだっただろうか。</p> myakura Autoprefixerのブラウザ指定をpackage.jsonの`browserlist`からする hatenablog://entry/10328749687216936688 2017-02-14T07:30:00+09:00 2017-02-14T07:30:30+09:00 Autoprefixerのブラウザの設定がpackgage.jsonに書けるようになっていた <p><a href="https://twitter.com/myakura/status/831173112582467585">さっきAutoprefixerの設定でいろいろ阿呆なことをして</a>、まあそれは解決して、ついでにリリースノートを見ていたら<a href="https://github.com/postcss/autoprefixer/releases/tag/6.6.0">6.6.0</a>でこんな機能が入っていたのを知る。</p> <blockquote><p>With Autoprefixer 6.6 you can specify browsers in <code>package.json</code> to reduce config files:</p> <pre><code>{ "private": true, "devDependencies": { "autoprefixer": "^6.6.0", "postcss": "^5.2.6" }, "browserslist": [ "last 2 versions", "ie 9" ] } </code></pre> <p>Note that we highly recommend specifying browsers in <code>browserslist</code> config or in <code>package.json</code> instead of Autoprefixer option.</p></blockquote> <p>これまでAutoprefixerのコードに書いてた対応させたいブラウザの範囲をpackage.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>の<code>browserslist</code>に書けるようになったとのこと。<a href="https://github.com/ai/browserslist">Browserslist</a>は<a href="https://caniuse.com">caniuse</a>のデータを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C0%A5%F3">ダン</a>プしたやつを文字列でクエリできるやつで、いつからかAutoprefixerが使っていたのは知っていたけど、いろいろ使いやすくなってたんだね。不勉強であった。うあー</p> <p>6.6.0時点でAutoprefixer以外にも、Stylelintやbabel-env-presetでも使われているとのこと。Autoprefixerは設定はコードじゃなくてpackage.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>とかのがおすすめと書いてるので、今後はこう書いたほうがいいのかな。</p> <h2>書いてみる</h2> <p>手元のpackage.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>とgulpfileをいじってみた。</p> <pre class="code lang-json" data-lang="json" data-unlink> &quot;<span class="synStatement">private</span>&quot;: <span class="synConstant">true</span>, ... &quot;<span class="synStatement">browserslist</span>&quot;: <span class="synSpecial">[</span> &quot;<span class="synConstant">last 1 version</span>&quot; <span class="synSpecial">]</span>, ... </pre> <p>こんな感じで書いて、gulpfileでAutoprefixerをかましてるコード</p> <pre class="code lang-javascript" data-lang="javascript" data-unlink> .pipe(postcss(<span class="synIdentifier">[</span> autoprefixer(<span class="synIdentifier">{</span> browsers: <span class="synIdentifier">[</span><span class="synConstant">'last 1 version'</span><span class="synIdentifier">]</span>, cascade: <span class="synConstant">false</span> <span class="synIdentifier">}</span>), ... </pre> <p>ここから<code>browsers: ['last 1 version'],</code>を削るだけ。<br/> さて実行…うごいた…多分。エラーが出てもしかしてデフォルトにフォールバックされてるかもしれないけど、たぶん動いてる。わーい。</p> <p>もうちょい読むと、package.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>だけじゃなくて、<code>$BROWSERSLIST</code>っていう<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%C4%B6%AD%CA%D1%BF%F4">環境変数</a>でもいいし、ルートに設定を書いた<code>browserslist</code>ファイルでもいいらしい。<a href="https://github.com/ai/browserslist#queries">READMEのQueriesなるセクション</a>に優先順位とかが書いてあった。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Analytics">Google Analytics</a>のデータを使う</h2> <p>これはBrowserlistというかcaniuseの機能なんだけど、caniuse.comのSettingsから<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Analytics">Google Analytics</a>のアカウントを連携させてやると、グローバルなブラウザのシェアでなく、管理下のサイトのそれに連動した情報を出してくれる。</p> <p>そのデータを<a href="https://github.com/ai/browserslist#custom-usage-data">なかなかなワンライナー</a>でファイルとして出力してやると、そいつをもとにしてくれるとのこと。ファイル出力はもうすこしスマートにできるといいな。</p> myakura するするさせたい:サイボウズ採用情報のアニメーション(その3) hatenablog://entry/6653812171396210194 2016-05-16T06:51:15+09:00 2018-12-07T17:09:50+09:00 サイボウズ採用情報のアニメーションがするするしてないので調べた件、SafariやFirefoxでも見てみたりもした。 <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A5%A4%A5%DC%A5%A6%A5%BA">サイボウズ</a>採用情報のアニメーションがするするしてないので調べた件、今回は雑記。</p> <ul> <li><a href="http://myakura.hatenablog.com/entry/2016/05/12/083000">その1</a> ― 何が起こっているのか調べる</li> <li><a href="http://myakura.hatenablog.com/entry/2016/05/13/143000">その2</a> ― 調べながら直しながらするするさせる</li> <li><strong>その3</strong> ― ちょっとしたことや他のブラウザでもするするさせる</li> </ul> <h2>描画領域とPaint Flashing</h2> <p><a href="http://myakura.hatenablog.com/entry/2016/05/12/083000">その1</a>でPaint flashingを見たときにはアイコンの周りに枠がついていたのに、<a href="http://myakura.hatenablog.com/entry/2016/05/13/143000">その2</a>で描画領域を見たら文書全体で起こっていたたのをふしぎに思ったひとがいるかもしれない。</p> <p>これはPaint flashingの説明 <q>Hightlights areas of the page that need to be repainted</q> というのをよく読むといいかも。緑色になったところは「再描画が必要になったところ」、paint invalidationを指している。なので変化していない箇所は緑色にならなかったわけだ。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>における“Paint”が何を指すかは、<a href="http://stackoverflow.com/questions/33173919/timeline-paint-profiler-in-devtools-suggests-everything-is-being-painted/33180232">Stack Overflowにある回答</a>が詳しい。</p> <h2>モバイルはどうなのか</h2> <p>今回使ったのはふだん使ってる<a class="keyword" href="http://d.hatena.ne.jp/keyword/MacBook%20Air">MacBook Air</a>。2011年モデルだし<a class="keyword" href="http://d.hatena.ne.jp/keyword/Air">Air</a>だし<a class="keyword" href="http://d.hatena.ne.jp/keyword/Mac">Mac</a>としてはだいぶしょぼい。それでもなんとかするするさせられた。</p> <p>ではもっとしょぼい環境はどうなるか。というわけで<a class="keyword" href="http://d.hatena.ne.jp/keyword/Nexus">Nexus</a> 5を繋いでリモート<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>してみた。 以下通常状態。<a class="keyword" href="http://d.hatena.ne.jp/keyword/MacBook%20Air">MacBook Air</a>と比べてCPUの使用率が高い。描画も引き続き高いけど、Scriptingも高いのが気になる。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160515/20160515162406.png" alt="f:id:myakura:20160515162406p:plain" title="f:id:myakura:20160515162406p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p><code>transform: translateX()</code> をつかったアニメーションに差し替えると、するするした。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160515/20160515162413.png" alt="f:id:myakura:20160515162413p:plain" title="f:id:myakura:20160515162413p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>いちおう大丈夫っぽい。ただ格安<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>などもっとしょぼい端末だと、CPUや<a class="keyword" href="http://d.hatena.ne.jp/keyword/GPU">GPU</a>がこれ以上に専有されるかもしれない。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>はどうだろう。<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>デ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>持ってないので試せないのだけど<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>さまなら大丈夫だろうと勝手に思って眠ることにする(みんなは試そう)。</p> <h2>他のブラウザの開発者ツール</h2> <p>今回は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a> DevToolsを使った。アクティビティの詳細を見られるので説明に便利なのと、まあみんな使ってるんでしょということで。<br>ただ<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>だけの最適化になってしまったらアレだ。他のブラウザはどうなのか。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>や<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>のDeveloper Tools/Web InspectorにもふつうにElementsパネルはある。<code>h</code> で要素も隠せる。</p> <p>Paint flashingもどちらにもある。<a href="https://developer.mozilla.org/en-US/docs/Tools/Paint_Flashing_Tool">Firefoxではハケのアイコン</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>はElementsパネルのパンくず右にあるブラシアイコンで同様のものが見られる。なお<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>は色相が常に変わり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>では赤色のハイライトになる。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160515/20160515163120.png" alt="f:id:myakura:20160515163120p:plain" title="f:id:myakura:20160515163120p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>件のアニメーションは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>では真っ赤になった。赤いほうが問題っぽさが増していいかもしれない(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>も昔は赤色だったけれども)。</p> <p>レイヤー表示。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>の場合はPaint flashingアイコンの横にある四角が4つのアイコンを押すと表示される。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160516/20160516063926.png" alt="f:id:myakura:20160516063926p:plain" title="f:id:myakura:20160516063926p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>ではDeveloper Toolsからできない。<code>about:config</code> から <code>layers.draw-borders</code> を <code>true</code> にすればいける。ちょっと面倒。<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=877567">Bug 877567</a>なのかな。</p> <p>で、肝心なタイムライン。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>, <a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>どちらにもあるんだけれど<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>ほど高機能ではない。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>が強すぎるというのはある。</p> <p>ただ今回くらいのレベルであれば、そんな問題はないかも。数秒ほど録る、繰り返しを見つける、時間を見てみる。これでそれなりにわかるかなあと。描画領域についてはとりあえず <code>will-change: transform</code> をコンソールからぶっこんでレイヤー作って確かめるとかね。いろんなサイトのタイムラインを録ってみて調べるうちに感覚が養えてくると思うので、いろいろ見てみてほしい。</p> <p>Edgeは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a>環境が手元にないのでわからないのだけど、<a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/documentation/f12-devtools-guide/performance/">ドキュメンテーション</a>を見る限りは結構強力そう。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>でするする</h2> <p>さて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>でもとのページのタイムラインを録ってみた。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160515/20160515172624.png" alt="f:id:myakura:20160515172624p:plain" title="f:id:myakura:20160515172624p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>スタイル計算と描画、タイマー発火が頻繁そうなことがわかる。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160515/20160515172649.png" alt="f:id:myakura:20160515172649p:plain" title="f:id:myakura:20160515172649p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>Layout &amp; Renderingという行を押したら詳細が見られる。Paintではその領域を見られるけど、これはinvalidationなのかな。ちょっとわからない。</p> <p>Web Inspectorに新しく入った<a href="https://webkit.org/blog/3996/introducing-the-rendering-frames-timeline/">Rendering Framesモード</a>でも見てみた。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160515/20160515172657.png" alt="f:id:myakura:20160515172657p:plain" title="f:id:myakura:20160515172657p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>1フレーム目にタイマー、2フレーム目に計算・描画が行われてて面白い。</p> <p>さてするするさせてみる。<code>transform</code> を使ったコードをぶっこんでまたタイムラインを録ってみる。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160515/20160515173631.png" alt="f:id:myakura:20160515173631p:plain" title="f:id:myakura:20160515173631p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>するするした。同じ方法が使えるようだ。</p> <p>なお、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>アニメーション版のレイヤーを見てみると謎の水色の枠がでてきた。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160516/20160516063943.png" alt="f:id:myakura:20160516063943p:plain" title="f:id:myakura:20160516063943p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>こいつはなんなんだろう…Web Inspectorは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%AD%A5%E5%A5%E1%A5%F3%A5%C6%A1%BC%A5%B7%A5%E7%A5%F3">ドキュメンテーション</a>があまりなく、さらには更新されてないのでけっこうつらい。ソース読むしかないのか……</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>でするする?</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>でもみてみる。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>のタイムライン(Performance)ツールは複数のタイムラインを保持できるのがうれしい。<br>現行のサイトを録ってみた。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160516/20160516064037.png" alt="f:id:myakura:20160516064037p:plain" title="f:id:myakura:20160516064037p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>あら、そのままでも60FPSに近い。Composite Layersにけっこう時間をとられているね。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160516/20160516064046.png" alt="f:id:myakura:20160516064046p:plain" title="f:id:myakura:20160516064046p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>Paintもすこしかかっている。描画範囲わからないのかな。もうちょっと調べないといけない。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160516/20160516064106.png" alt="f:id:myakura:20160516064106p:plain" title="f:id:myakura:20160516064106p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>アニメーションに置き換えたものがこちら。タイマーはなくなったけど、ちょっとところどころフレームが落ちてしまっている。Composite Layersの負荷が変わってないので、もともと負荷が高いのかな。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160516/20160516064127.png" alt="f:id:myakura:20160516064127p:plain" title="f:id:myakura:20160516064127p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>あとスタイル再計算も走っている。Restyle Hintが<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>アニメーションとなっているので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Gecko">Gecko</a>だとスタイルの再計算が走ってしまうのかな。ふむー</p> <p>ただ見た目をいうと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>アニメーションのほうがするするはしているんだよね。データには現れづらいところなのかな…ちょっと心残り。</p> <hr /> <p>もうちょっとなんか考えてた気がするんだけど、メモしてなかったのともう書き疲れたのでこのへんで。<br>みんなもするするさせるんだよ。</p> myakura するするさせたい:サイボウズ採用情報のアニメーション(その2) hatenablog://entry/6653812171395909643 2016-05-13T14:30:00+09:00 2018-12-07T17:04:05+09:00 サイボウズの採用情報ページのアニメーションがするするしていない問題。レイヤーを分けて描画範囲を小さくしたり、CSS Transformsでアニメーションさせることによってするするさせられた。 <p><a href="http://cybozu.co.jp/company/job/recruitment/">サイボウズの採用情報ページ</a>にあるアニメーションがするするしていない。ので<a href="http://myakura.hatenablog.com/entry/2016/05/12/083000">前回</a>は何がおこってるのか見てみた。</p> <p>今回はするするさせられないか、がんばってみる。</p> <ul> <li><a href="http://myakura.hatenablog.com/entry/2016/05/12/083000">その1</a> ― 何が起こっているのか調べる</li> <li><strong>その2</strong> ― 調べながら直しながらするするさせる</li> <li><a href="http://myakura.hatenablog.com/entry/2016/05/16/065115">その3</a> ― ちょっとしたことや他のブラウザでもするするさせる</li> </ul> <h2>アニメーションを止める</h2> <p>まず、いまの<a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a>ベースなアニメーションを止める。<br>コンソールに以下をぶっこめばアニメーションが止まって、背景も初期位置に戻る。</p> <pre class="code lang-javascript" data-lang="javascript" data-unlink>jQuery(<span class="synConstant">'.icon'</span>).stop().css(<span class="synConstant">'backgroundPosition'</span>, <span class="synConstant">''</span>) </pre> <p>チェーンもできるし<a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a>べんりだね。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>アニメーションにしてみる</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a>のアニメーションを別の方法に書き換えるわけだけど、今は2010年代も後半だ。使うなら<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>アニメーションしかない。とくに右から左へ一方向っていう単純な動きならなおさらだ。</p> <p>さっきの<a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a>のコードは、こう変換できるかな。</p> <pre class="code lang-css" data-lang="css" data-unlink><span class="synComment">@keyframes</span> loop-icon <span class="synIdentifier">{</span> <span class="synConstant">from</span> <span class="synIdentifier">{</span> <span class="synType">background-position</span>: <span class="synConstant">0</span> <span class="synIdentifier">}</span> <span class="synConstant">to</span> <span class="synIdentifier">{</span> <span class="synType">background-position</span>: <span class="synConstant">-1680px</span> <span class="synIdentifier">}</span> <span class="synIdentifier">}</span> <span class="synIdentifier">.icon</span> <span class="synIdentifier">{</span> <span class="synType">animation-name</span>: loop-<span class="synConstant">icon</span>; <span class="synType">animation-duration</span>: <span class="synConstant">60480ms</span>; <span class="synComment">/* 1680×36 */</span> <span class="synType">animation-timing-function</span>: <span class="synConstant">linear</span>; <span class="synType">animation-iteration-count</span>: infinite; <span class="synComment">/* animation: loop-icon 60480ms linear infinite; でもOK */</span> <span class="synIdentifier">}</span> </pre> <p>で、これを <code>document.head.innerHTML += <code>&lt;style&gt;...&lt;/style&gt;</code></code> とかでくるんでコンソールにぶっこむとアイコンが動き出す。おー、なんとなくするする動いてる感じ。</p> <h2>描画の詳細を見てみる</h2> <p>なんとなくじゃだめなので、またタイムラインを録ってみる。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160513/20160513131612.png" alt="f:id:myakura:20160513131612p:plain" title="f:id:myakura:20160513131612p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>およ…?</p> <p>CPUの使用量が下がった感じはするけど、引き続きジャンクな感じ。<br>拡大すると、たしかに下がってはいる。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160513/20160513131746.png" alt="f:id:myakura:20160513131746p:plain" title="f:id:myakura:20160513131746p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>あと、Summaryから“Scripting”の項目が消えている。これは<a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a>のアニメーションが <code>setInterval()</code> ベースだったんだけど、それがなくなったからだ。</p> <p>さて、多少の成果が出たけれど、これではするするとは言えない。もっと調べよう。<br>拡大して、太い緑色のところをクリックすると、その描画についての詳細を見られる。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160513/20160513132737.png" alt="f:id:myakura:20160513132737p:plain" title="f:id:myakura:20160513132737p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>描画範囲(Dimensions)が「1362 × 6935」となっている。なんと、アニメーションはページの一部しかないのに、どうやらページ全体を描画しているらしい。だから負荷が高いまま。</p> <h2><code>will-change</code> で別レイヤーに移す</h2> <p>ページの一部(高さ120px)を動かすためだけにページ全体(6935px)が毎回描画されるのはだいぶつらい。再描画の範囲を最小にしたい。そこで注目するのが、さっきのSummaryにあった「Layer Root」という項目だ。</p> <p>ブラウザの描画領域は一枚なときもあるけど、合成レイヤー(compositing layer)という複数のレイヤーからなっていることもある。今回のように一部だけ動くとか、そういう際にブラウザが自動的にレイヤーを切って管理してくれる。OHPシート重ねて動かすみたいなやつだ。</p> <p>というわけで、ブラウザに「動くのここだけだからレイヤー切ってよー」というのを示して全体を描画させないようにする。これには <a href="https://developer.mozilla.org/docs/Web/CSS/will-change"><code>will-change</code> なるプロパティ</a>を使う。値にプロパティ名を指定すると、ブラウザはその要素上のそのプロパティが変化するのに適した処理をしてくれるようになる。</p> <p>レイヤーを新たに作りたい場合、値に <code>transform</code> を指定するのがおまじないだ。</p> <pre class="code lang-css" data-lang="css" data-unlink><span class="synIdentifier">.icon</span> <span class="synIdentifier">{</span> <span class="synType">animation-name</span>: loop-<span class="synConstant">icon</span>; <span class="synType">animation-duration</span>: <span class="synConstant">60480ms</span>; <span class="synType">animation-timing-function</span>: <span class="synConstant">linear</span>; <span class="synType">animation-iteration-count</span>: infinite; will-change: transform; <span class="synIdentifier">}</span> </pre> <p>古の <code>-webkit-transform: translate3d(0, 0, 0)</code> と変わらないじゃんと思うかもしれない。ハック感は否めないけど、でもいちおうオプトインだから。名前も「will-change」であくまで意図だしブラウザが今後もこの挙動とは限らないから(もごもご)……</p> <h2>レイヤーを確認する</h2> <p>レイヤーを切ったのはいいけれど、どう確認すればいいか。もいちどDevToolsのRenderingメニューを開く。そこにある「Layer Borders」をチェックすれば、レイヤーの境界にボーダーが引かれるので、どこにレイヤーがあるかがわかる。</p> <p>以下はもともとのページのレイヤー。レイヤーの境界は薄いオレンジで、ページの端についている。ページ全体が一枚のレイヤーみたいだ。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160513/20160513140733.png" alt="f:id:myakura:20160513140733p:plain" title="f:id:myakura:20160513140733p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>水色の水平線が見える。これはタイルというレイヤーのいち領域の区切りを示している。<br>右と下に緑色の矩形が見えるけど、どうやらスクロールバーの領域もレイヤーの一種みたいだ。</p> <p>以下は <code>.icon</code> に <code>will-change: transform</code> を与えてレイヤー化したもの。アイコン周りに新しいオレンジの枠ができたのがわかる。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160513/20160513140745.png" alt="f:id:myakura:20160513140745p:plain" title="f:id:myakura:20160513140745p:plain" class="hatena-fotolife" itemprop="image"></span></p> <h2>レイヤー分けた効果を確認</h2> <p>ではタイムラインを録ってみよう。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160513/20160513142111.png" alt="f:id:myakura:20160513142111p:plain" title="f:id:myakura:20160513142111p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>ふむ。ジャンクはまだあるけど、描画の負荷がだいぶ減っている。1フレームとばしで60FPSも達成している。またちょっと進んだね。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160513/20160513142126.png" alt="f:id:myakura:20160513142126p:plain" title="f:id:myakura:20160513142126p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>あんなに太かったPaintもほっそくなって、描画領域も「1362 × 120」に、レイヤールートも狙い通り <code>#document</code> から <code>div.icon</code> になった。</p> <p>しかしまだジャンクがあるのが気になる。確かに見るとまだガタガタしている。<br>あと、Paintingが減ってはじめて気になったのが紫色のRendering。毎回なにを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%F3%A5%C0%A5%EA%A5%F3%A5%B0">レンダリング</a>しているのか?そう、背景画像だ。</p> <h2><code>transform</code> でするする</h2> <p>実は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>アニメーションにしたから負荷が減るというのは限定的な話で、プロパティによってはレイアウト、スタイルの計算、描画がはしってしまう。レイアウトはスタイル計算を、スタイル計算は描画を引き起こすので、できるかぎり前の段階からの最小化が望ましい。</p> <p>プロパティごとに引き起こされるレイアウト・スタイル計算・描画は、Paul Lewisらがまとめている。</p> <ul> <li><a href="https://csstriggers.com/">CSS Triggers</a></li> </ul> <p>最近Blink以外のエンジンも頑張っている。<br>さて、<a href="https://csstriggers.com/background-position"><code>background-position</code> の項</a>をみると、<q>it will cause painting to occur</q> とある。なので描画は結局おこってしまう。あとスタイルの計算もはしってしまう。なので<a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a>まわりの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>・レイアウトの負荷がなくなるだけで、コストの掛かる描画は残ったままになる。</p> <p>どうすればいいか。アニメーションによるのでどうにもできないケースもあるだろうけど、今回のアニメーションであれば <code>transform</code> の <code>translateX()</code> に置き換えるといい。<a href="https://csstriggers.com/transform"><code>transform</code> は描画も起こさない</a>ので、この負荷も下げられる。というわけでこちらにしよう。</p> <p>背景画像の繰り返しを利用してずっと流れているように見せているので、書き換えはちょっと工夫が必要。今回は <code>.icon</code> の幅を広げて、それを <code>translateX()</code> で動かすようにした。</p> <pre class="code lang-css" data-lang="css" data-unlink><span class="synComment">@keyframes</span> loop-icon-transform <span class="synIdentifier">{</span> <span class="synConstant">from</span> <span class="synIdentifier">{</span> <span class="synType">transform</span>: <span class="synIdentifier">translateX(</span><span class="synConstant">0px</span><span class="synIdentifier">)</span> <span class="synIdentifier">}</span> <span class="synConstant">to</span> <span class="synIdentifier">{</span> <span class="synType">transform</span>: <span class="synIdentifier">translateX(</span><span class="synConstant">-1680px</span><span class="synIdentifier">)</span> <span class="synIdentifier">}</span> <span class="synIdentifier">}</span> <span class="synIdentifier">.kintone</span> <span class="synIdentifier">{</span> <span class="synType">overflow</span>: <span class="synConstant">hidden</span>; <span class="synIdentifier">}</span> <span class="synIdentifier">.icon</span> <span class="synIdentifier">{</span> <span class="synType">width</span>: <span class="synConstant">3360px</span> <span class="synSpecial">!important</span>; <span class="synType">animation</span>: loop-<span class="synConstant">icon</span>-transform <span class="synConstant">60480ms</span> <span class="synConstant">linear</span> infinite; <span class="synIdentifier">}</span> </pre> <p>ウインドウの幅が大きいと端が見えちゃうだろうけれど、だいたいカバーできるだろう。<br>もうちょっといいつくりがあるのかもしれない。<code>translateX()</code> で動かせて、切れ端が見えないのならなんでもいい。</p> <p>なお、今回は <code>will-change</code> を指定していない。というのも、指定しなくてもレイヤーを分けてくれたから。<code>will-change</code> もこのアニメーションの自動レイヤーわけもブラウザ依存なので、対応環境によってはつけないといけないかもしれない。</p> <p>ではタイムラインを録ってみよう。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160513/20160513143936.png" alt="f:id:myakura:20160513143936p:plain" title="f:id:myakura:20160513143936p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>ててーん。ジャンクなし。だいたい60FPS。RenderingとPaintingも消えた。 <br>見た目もするするしている。するするさせられた!</p> <hr /> <p>というわけで、するするさせたいという目標はいちおう達成できたかな。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%C9%A4%A6%A4%BE%A4%B4%CD%F8%CD%D1%A4%AF%A4%C0%A4%B5%A4%A4%A1%A3">どうぞご利用ください。</a></p> <p>ただちょっとだけ気になることとか、あと少し書いときたいこともある。そいつはまた次回。</p> <p>(追記):書いたよー</p> <ul> <li><a href="http://myakura.hatenablog.com/entry/2016/05/16/065115">するするさせたい:サイボウズ採用情報のアニメーション(その3)</a></li> </ul> <h2>おまけ:試してみよう</h2> <p>どんなコードをコンソールにぶっこんだかちょっと書いとこう。おためしあれ。</p> <p><code>background-position</code> 版の<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>アニメーションに置き換え。</p> <pre class="code lang-javascript" data-lang="javascript" data-unlink>jQuery(<span class="synConstant">'.icon'</span>).stop().css(<span class="synConstant">'backgroundPosition'</span>, <span class="synConstant">''</span>) <span class="synStatement">document</span>.head.innerHTML += `&lt;style&gt;@keyframes loop-icon <span class="synIdentifier">{</span> from <span class="synIdentifier">{</span> background-position: 0 <span class="synIdentifier">}</span> to <span class="synIdentifier">{</span> background-position: -1680px <span class="synIdentifier">}</span> <span class="synIdentifier">}</span> .icon <span class="synIdentifier">{</span> animation-name: loop-icon; animation-duration: 60480ms; animation-timing-<span class="synIdentifier">function</span>: linear; animation-iteration-count: infinite; <span class="synIdentifier">}</span>&lt;/style&gt;` </pre> <p><code>will-change: transform</code> はStyleパネルから追加している。クリックでオンオフさせやすいので。</p> <p>以下は <code>translateX</code> 版の<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>アニメーション(最終版)に置き換えるもの。</p> <pre class="code lang-javascript" data-lang="javascript" data-unlink>jQuery(<span class="synConstant">'.icon'</span>).stop().css(<span class="synConstant">'backgroundPosition'</span>, <span class="synConstant">''</span>) <span class="synStatement">document</span>.head.innerHTML += `&lt;style&gt;@keyframes loop-icon-transform <span class="synIdentifier">{</span> from <span class="synIdentifier">{</span> transform: translateX(0px) <span class="synIdentifier">}</span> to <span class="synIdentifier">{</span> transform: translateX(-1680px) <span class="synIdentifier">}</span> <span class="synIdentifier">}</span> .kintone <span class="synIdentifier">{</span> overflow: hidden; <span class="synIdentifier">}</span> .icon <span class="synIdentifier">{</span> width: 3360px !important; animation: loop-icon-transform 60480ms linear infinite; <span class="synIdentifier">}</span>&lt;/style&gt;` </pre> <p>いま考えたらTemplate Strings使ってるんだからべつに改行取っ払うこともなかったな…</p> myakura するするさせたい:サイボウズ採用情報のアニメーション(その1) hatenablog://entry/6653812171395281698 2016-05-12T08:30:00+09:00 2018-03-14T11:23:41+09:00 サイボウズの採用情報ページのアニメーションがするするしていなかったので、Chrome DevToolsを使って何が起こってるのか調べてみた。 <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A5%A4%A5%DC%A5%A6%A5%BA">サイボウズ</a>の採用情報ページを見ていた。</p> <ul> <li><a href="http://cybozu.co.jp/company/job/recruitment/">サイボウズ | 採用情報(新卒・キャリア)</a></li> </ul> <p>といっても受けるとかではなく、<a href="https://twitter.com/myakura/status/720858506283225088">ただ性格悪いことを思っていた</a>だけなんだけど。</p> <p>Kintoneのセクションでアプリっぽいアイコンたちが右から左へと流れているんだけど、それがガタガタとしている。するするしていない。するするさせたい。</p> <p>というわけで、何が起こっているのかを調べてみようかと。何回かにわけて書くよ。</p> <ul> <li><strong>その1</strong> ― 何が起こっているのか調べる</li> <li><a href="http://myakura.hatenablog.com/entry/2016/05/13/143000">その2</a> ― 調べながら直しながらするするさせる</li> <li><a href="http://myakura.hatenablog.com/entry/2016/05/16/065115">その3</a> ― ちょっとしたことや他のブラウザでもするするさせる</li> </ul> <h2>アニメーションの実装を調べる</h2> <p>あとのことを考えて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a> DevToolsを使う。</p> <p>まず、該当の流れるアイコンのところで右クリックしてinspectする。Elementsパネルで、<code>&lt;div class="icon"&gt;</code> という要素がハイライトされる。<code>div.icon</code> には <code>style</code> 属性がついていて、そこにセットされた <code>background-position</code> の値が絶えず変化しているのが見える。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160510/20160510083150.png" alt="f:id:myakura:20160510083150p:plain" title="f:id:myakura:20160510083150p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>というわけで、背景画像の位置を<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>で逐次書き換えるっていう、クラシックなアニメーションの実装方法なのがわかる。</p> <p><a href="http://cybozu.co.jp/company/job/recruitment/common/js/recruitment.js">使われているJavaScriptファイル</a>のソースを見てみる。<code>.icon</code> で検索すると見つかった。</p> <pre class="code lang-javascript" data-lang="javascript" data-unlink><span class="synIdentifier">var</span> loopIcon = <span class="synIdentifier">function</span>()<span class="synIdentifier">{</span> $(<span class="synIdentifier">this</span>).css(<span class="synIdentifier">{</span>backgroundPosition:<span class="synConstant">'0'</span><span class="synIdentifier">}</span>); $(<span class="synConstant">'.kintone .icon'</span>).animate(<span class="synIdentifier">{</span>backgroundPosition:<span class="synConstant">'-1680px'</span><span class="synIdentifier">}</span>, 1680*36, <span class="synConstant">'linear'</span>, loopIcon); <span class="synIdentifier">}</span> </pre> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a>でやっているみたい。で、こういう<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>で逐次<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>を書き換えていくアニメーションにはたいてい描画絡みの問題がある。</p> <h2>描画されている箇所をみてみる</h2> <p>描画について見てみる。DevToolsの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%F3%A5%C0%A5%EA%A5%F3%A5%B0">レンダリング</a>設定パネルを使う。</p> <p>DevToolsのメニューで「Other tools」→「Rendering settings」を選ぶと、下からにゅっとConsoleなどがついたパネルがが生えてくる。Renderingタブが選択されていると思うので、その中にある「Enable paint flashing」をチェックすると描画の変化する箇所に緑色の枠がつく。スクロールしたり、リンクにカーソルを重ねたりすると、「描画の変化」がどういうものかわかると思う。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160510/20160510083928.png" alt="f:id:myakura:20160510083928p:plain" title="f:id:myakura:20160510083928p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>さて件のアニメーション。ずっと枠がついたまま。なので、この箇所が絶えず描画されているのがわかる。</p> <h2>タイムラインをとってみる</h2> <p>こいつがパフォーマンスにどれくらい影響しているのか、もうちょっと見てみる。<br>Timelineパネルを開いて、左上にある黒丸を押して2〜3秒ほど録る。</p> <p>以下は<a class="keyword" href="http://d.hatena.ne.jp/keyword/MacBook%20Air">MacBook Air</a> 11" (mid-2011モデル、メモリ4GB)上の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a> Canary (M52)、ちょこちょこブラウザやエディタを開いた状態で録ったもの。記録する際に、PaintとScreenshotのみチェックした。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160512/20160512120322.png" alt="f:id:myakura:20160512120322p:plain" title="f:id:myakura:20160512120322p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>とれたけどいろいろ情報が多いので、まず上のオーバービューと呼ばれる箇所を見る。その下のフレームチャートなどはあとから見よう。</p> <p>オーバービューは、フレームと<a class="keyword" href="http://d.hatena.ne.jp/keyword/FPS">FPS</a>、CPUのアクティビティ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A1%BC%A5%F3%A5%B7%A5%E7%A5%C3%A5%C8">スクリーンショット</a>を見せて大まかなところを把握するためのところ。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160512/20160512120342.png" alt="f:id:myakura:20160512120342p:plain" title="f:id:myakura:20160512120342p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>フレームのところにあるがたがたした緑色の領域は<a class="keyword" href="http://d.hatena.ne.jp/keyword/FPS">FPS</a>で、てっぺんが60FPSを指す。その上に見られる赤い線は60FPSを切ったフレームで、いわゆる「フレーム落ち」、海外のWebパフォーマンス界隈だと “jank” と呼ばれるやつを指している。<br>つまり上に赤い線が見えず、緑色の面積が大きいほどいい。</p> <p>で、かなりのところでジャンクが発生している。環境によっては赤いのを見ないかもしれないけど、今回はこうなった。</p> <p>さて、フレームの下、CPUのアクティビティを見る。ちょこちょこと濃い緑色の山があって、たまに紫や橙が見られる。<br>上のフレームのとこと違って、こちらは山が低い方がいい(負荷が少ないから)。ではこの山になってるとこで、なにがおこっているのか。</p> <h2>フレームチャートを見る</h2> <p>調べるといってもどこを見るといいか。見直すと、ちょっとパターンが感じられる箇所があった。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160512/20160512124009.png" alt="f:id:myakura:20160512124009p:plain" title="f:id:myakura:20160512124009p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>だいたい等間隔で高い山が現れているので、ここを詳しく見ると、パフォーマンスの問題が見えてきそうだ。そこを見てみよう。<br>オーバービューのところで範囲選択すると、下のフレームチャートが該当する範囲のものに切り替わる。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160512/20160512131823.png" alt="f:id:myakura:20160512131823p:plain:w600" title="f:id:myakura:20160512131823p:plain:w600" class="hatena-fotolife" style="width:600px" itemprop="image"></span></p> <p>一番下のペーンに、アクティビティごとにかかった時間が円グラフにまとめられている。“Painting”と“Other”が多い。後者はさておいて、描画関連の処理は全体400ms中38msと、1割弱もの時間がかかっているのがわかる。</p> <h2>本当にそこなのか、隠してみる</h2> <p>さて、タイムラインを録ってアイコン周りの描画の負荷が高くてフレームが落ちているようになんとなく感じていたものの、それが直接の原因なのかを確かめていなかった。どうすればいいか。隠せばいい。</p> <p>もういちどElementsパネルに戻って、<code>div.icon</code> を選択し、<code>h</code> キーを押す。そうするとアイコンがぱっと消えてしまう。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160512/20160512141442.png" alt="f:id:myakura:20160512141442p:plain" title="f:id:myakura:20160512141442p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p><code>div.icon</code> に <code>__web-inspector-hide-shortcut__</code> なんて変なclassがついたけど、中身は <code>visibility: hidden</code> を指定しているだけ。<br><code>visibility: hidden</code> が当たると描画関連の処理が行われなくなる。ではこの状態でタイムラインを録ってみよう。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20160512/20160512142003.png" alt="f:id:myakura:20160512142003p:plain" title="f:id:myakura:20160512142003p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>全体的にいろいろ薄くなった。ジャンクな赤色も見えない。<a class="keyword" href="http://d.hatena.ne.jp/keyword/FPS">FPS</a>のグラフがなくなっているのはアイドル状態になった、つまりは活動しなくてもよくなったから。</p> <hr /> <p>というわけで、アイコンのアニメーションが描画に負担をかけてるのがわかった。では負担をかけない、するするするアニメーションにどう作り変えていけばいいだろうか。長くなったのでそいつは次回に。</p> <p>(追記):次回書いたよー</p> <ul> <li><p><a href="http://myakura.hatenablog.com/entry/2016/05/13/143000">するするさせたい:サイボウズ採用情報のアニメーション(その2)</a></p></li> </ul> myakura するするさせたい hatenablog://entry/6653586347155050994 2016-03-01T20:58:31+09:00 2016-03-01T20:58:31+09:00 昨年くらいからWebの描画まわりのパフォーマンスについて調べたりしている。何をしたいのかと言うと、するするさせたい。 するする? あくまで自分の傾向なんだけど、読み込まれるまで時間がかかるというよりは、ページのスクロールでひっかかりがあったり、クリックしたときのアクションがブロックされたりする方が、不満がある。 そこらへんをなんとかしたいなと。 もうちょい具体的に もうちょっと技術的に言うなら、余計なreflowやrepaintをなくすとか、render blockingな要因を減らすとか、そういうところだろうか。後者については、するする関係ないと言われるかもしれないけれど、そこも描画に依存す… <p>昨年くらいからWebの描画まわりのパフォーマンスについて調べたりしている。<br />何をしたいのかと言うと、するするさせたい。</p> <h2>するする?</h2> <p>あくまで自分の傾向なんだけど、読み込まれるまで時間がかかるというよりは、ページのスクロールでひっかかりがあったり、クリックしたときのアクションがブロックされたりする方が、不満がある。</p> <p>そこらへんをなんとかしたいなと。</p> <h3>もうちょい具体的に</h3> <p>もうちょっと技術的に言うなら、余計なreflowやrepaintをなくすとか、render blockingな要因を減らすとか、そういうところだろうか。後者については、するする関係ないと言われるかもしれないけれど、そこも描画に依存するところなので……</p> <h2>というわけで</h2> <p>そこら辺のこと書いたりお仕事にしてこうかと。仕事になるかなー……</p> myakura Progressive Web Appsとは hatenablog://entry/6653586347145630266 2015-11-18T05:39:39+09:00 2015-11-18T05:39:39+09:00 Chrome Dev Summitに来ている。 今年のChrome Dev Summitは日ごとにテーマが分かれていて、初日がProgressive Web Apps、2日目がRAILらしい。RAILはGooglerがちまちまと話してるけど、前者についてはまだそんな離されてない気がする。 というわけでセッション聞きながらなんとなく書いてみよう(なのでセッションまとめではないよ)。 アプリに「なっていく」「Web」 Progressive Web Appsは、Alex Russell先生が6月にブログで提唱して、そこからプロモートしているもの。“progressive”を訳すと「漸進的」やら「進… <p><a href="https://developer.chrome.com/devsummit">Chrome Dev Summit</a>に来ている。</p> <p>今年の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a> Dev Summitは日ごとにテーマが分かれていて、初日がProgressive Web Apps、2日目がRAILらしい。RAILはGooglerがちまちまと話してるけど、前者についてはまだそんな離されてない気がする。</p> <p>というわけでセッション聞きながらなんとなく書いてみよう(なのでセッションまとめではないよ)。</p> <h2>アプリに「なっていく」「Web」</h2> <p>Progressive Web Appsは、Alex Russell先生が6月に<a href="https://infrequently.org/2015/06/progressive-apps-escaping-tabs-without-losing-our-soul/">ブログで提唱</a>して、そこからプロモートしているもの。“progressive”を訳すと「漸進的」やら「進行性」とかになるけれど、そのまま訳すより「アプリになっていくWeb」と砕いて解釈するとわかりやすそう。</p> <p>アプリに「なっていく」とは何かなんだけど、Webアプリが「使ってるうちにネイティブアプリと同じような体験を備える」ってところなのかな。なので基本的にWebアプリというのは変わらない。</p> <p>また、「Web」というのもポイント。「『Web技術』を使ったアプリ」ではなくて、サーバにホストされURLを持つ、「Web上にあるアプリ」というのが重要。</p> <p>なんとなく「モバイルをキャッチアップする」というのに向いていたここ最近のWebプラットフォーム。ブラウザのパフォーマンス改善やら、新しい<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>などよい点もあったけれど、ちょっとそこが行き過ぎてしまった感もある。モバイルであんま使えそうにない<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>いらなくねって言って顰蹙買ったりとかね。</p> <p>Progressive Web Appsはそこからちょっと立ち返って、「インストール不要で使える」「リンクできる」「ストアなどの制限なく誰でも自由に開発できる」といったWebの性質を活かすことに主眼を置き直し、そのうえで発展を見ているように感じる。</p> <p>でも、いい点だけ押してても特に何も変わらない。PWAはモバイルのアプリと比べて厳しかった「エンゲージメント」に着目して、そこを改善して、そして辿り着けたものかなあと。</p> <h2>アプリになっていくには</h2> <p>「アプリに『なっていく』」っていうのはどういうことなのか。Webサイトがどうなったらアプリとして感じられるようになるのか。</p> <p>ひとつは、アクセスの起点。Webアプリの場合、ブラウザのアドレスバーから入力したり検索したりでたどり着くことが多いだろう(Webページなら<a class="keyword" href="http://d.hatena.ne.jp/keyword/SNS">SNS</a>や検索からのが多そうだけれど)。一方でアプリはホーム画面やローンチャにあるアイコンから立ち上げることがかなり多いと思う。どっちが「アプリ」として楽かというとたぶん後者になる。じゃあ、Webアプリをホーム画面とかに登録できるようにすればいい。ホーム画面にはアイコンがついて、タップしたらアプリっぽくWebアプリがブラウザで開かれるといい。</p> <p>ひとつは、起動した時の感覚。「アプリ」として使うには、オフラインでも「ガワ」や最低限のコンテンツは表示させておきたいし、単体で完結できるものならロケーションバーとかは消しときたい。そういう風にさせられればいい。</p> <p>ひとつは、起動してない時の関係。ブラウザを開いてない時でも、提示されたい情報や、アップデートされてると嬉しいデータなんかがある。そうさせよう。プッシュ通知とか同期ができるようになるといい。</p> <p>そしてこういう体験は強制ではなく、それを好みそうと思う人に、適当なタイミングで促せばいい。ブラウザがアクセスしたパターンをみて、アプリとして使ってそうだったら「もっとアプリっぽくしてみない?」と言う。Webアプリが「アプリインストールしない?」とか、最近見ないけど「ホーム画面に登録してみない?」っていうのを勝手実装するんじゃなくて。</p> <h2>あたらしい?</h2> <p>具体的な技術を挙げるなら、Web App Manifest、Service Workerがインストールまわりを、Push <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>とNotifications <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>、Web App Manifestの一部メンバがエンゲージメントまわりを担当する。</p> <p>ただ、こういう新しい機能を待たずとも、やろうと思えばそれなりにできていただろう。Service Workerで初めて広くもたらされるのはプッシュくらいで、オフラインなどはAppCache使えば(つらいだろうけど)なんとかなる。ホーム画面への追加も、ブラウザの機能で前からある。</p> <p>マーケティング用の単語というとそうかもね、というところ。でも概念に名前つけるのは、広めることを考えるとそれなりに重要だろう。ふんわりした「Webアプリ」の再定義や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D0%A1%BC%A5%ED%A1%BC%A5%C9">オーバーロード</a>はしづらいだろう。あとは開発はそれなりにつらいものだっただろうから、PWAを前提に機能スタックを整備し、その上で名前をつけられたので、そんなに無意味ではないかなあと。</p> myakura すこし開かれたWHATWG HTML hatenablog://entry/6653458415123179411 2015-10-05T07:30:00+09:00 2015-10-16T08:13:46+09:00 WHATWG HTMLの策定がGitHubに移ったことを受けてHTMLの今後を考える。 <p>8月末のことなんだけれど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/WHATWG">WHATWG</a> HTMLの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%C5%CD%CD%BD%F1">仕様書</a>が<a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a>に移った。</p> <ul> <li><a href="https://lists.w3.org/Archives/Public/public-whatwg-archive/2015Aug/0027.html">[whatwg] HTML spec now on GitHub (from Ian Hickson on 2015-08-27)</a></li> </ul> <p>体制も少し変わって、HixieがひとりでやっていたHTML仕様の作業に<a href="https://github.com/whatwg/html/commit/1e63583611c795b8f23f85bc3c2a96ff97c4d3fb">AnneやDomenicなども直接関わるようになった</a>。Issuesでの議論やPull Requestの受け付けも始まり、だいぶモダンな策定環境になった。</p> <h2>これまでの<a class="keyword" href="http://d.hatena.ne.jp/keyword/WHATWG">WHATWG</a> HTMLと<a class="keyword" href="http://d.hatena.ne.jp/keyword/HTML5">HTML5</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%C5%CD%CD%BD%F1">仕様書</a></h2> <p>これまでの<a class="keyword" href="http://d.hatena.ne.jp/keyword/WHATWG">WHATWG</a> HTMLは長らく<a class="keyword" href="http://d.hatena.ne.jp/keyword/Subversion">Subversion</a>サーバで運用されていた(もしかすると<a class="keyword" href="http://d.hatena.ne.jp/keyword/CVS">CVS</a>時代もあったかも)。</p> <p>HTML<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%C5%CD%CD%BD%F1">仕様書</a>は基本的に<a href="https://github.com/whatwg/html/blob/master/source">1枚のHTMLファイル</a>に書かれていて、それを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB">ツール</a>で切り出しmultipage版やPDF版、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Web%20Developer">Web Developer</a> Editionなどを生成していた(あ、<code>&lt;picture&gt;</code>については、<a href="https://github.com/ResponsiveImagesCG/picture-element">Simon PietersがRICGで作業してたもの</a>をパッチとして取り込んでいたので、多少いびつなことになっていたけど)。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/W3C">W3C</a>での<a class="keyword" href="http://d.hatena.ne.jp/keyword/HTML5">HTML5</a>(関連)<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%C5%CD%CD%BD%F1">仕様書</a>も、<a class="keyword" href="http://d.hatena.ne.jp/keyword/W3C">W3C</a>版のパッチが必要なところや、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Canvas">Canvas</a> 2D仕様とかの分割には<a href="https://github.com/w3c/html/commit/f2191ed8f5ca8956cd6bd07617de172845e9d086">ソース中に特殊なコメントを入れて</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB">ツール</a>がそれをもとにそれぞれの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%C5%CD%CD%BD%F1">仕様書</a>をつくるなんてことをしていた。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/W3C">W3C</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%C5%CD%CD%BD%F1">仕様書</a>は統一的な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB">ツール</a>が最近になってようやく運用されはじめたけど、それ以前のものは仕様やEditorによって違っていて、それが他のEditorの参入障壁になっていた気がする。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a>でのコミュニケーション</h2> <p>仕様(書)がオープンな環境にうつったこと、またHixie以外の人が積極的に関わり始め、多少なりとも変化が感じられる。</p> <p>ひとつは<a class="keyword" href="http://d.hatena.ne.jp/keyword/W3C">W3C</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/HTML5">HTML5</a>仕様との差を埋める提案が少しずつ出たこと。たとえば<a href="https://github.com/whatwg/html/commit/8d1c8affec71058de29f8051cb2fa7f7bbad1fe6">パーザは<code>&lt;rb&gt;</code>などに対応した</a>(conformingになってないのは厄介だけど)し、<a class="keyword" href="http://d.hatena.ne.jp/keyword/ARIA">ARIA</a>との関わりについては<a href="https://github.com/whatwg/html/commit/f619b0c0dfa6076d738c90e0d115221efc7cd003">Steve Faulknerの仕様を参照するように変更</a>された。</p> <p>とはいってもこれはHixieが拘りをなくしたところなだけで、そうでないものはやっぱり手強そう。<code>&lt;main&gt;</code>の違い(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%A3%BF%F4">複数</a>書けるか書けないか)については<a href="https://github.com/whatwg/html/issues/100">Issue</a>がたったもの燃えている。<code>&lt;hgroup&gt;</code>消そうみたいなIssueが経つと言うとまた荒れるんじゃないかな。Hixieの考えが悪いってわけでは必ずしもないんだけど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a>で運営されているものが持つオープンさとはだいぶ差があるのでそこらへんどうなるかな。バランスとれるといいんだけど。</p> <h2>HTMLはどうなってくのかね</h2> <p>HTMLの策定は、集まった<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B9%A5%B1%A1%BC%A5%B9">ユースケース</a>やデータを元にHixieがうんうんと考えデザインされたものが仕様に出てきて、それをレビューするというフローだった。Web技術の策定にかけるリソースが足りてない2000年台前半から半ばは、執念あるひと(Hixie)が居ることで仕様やWebが進んだ。</p> <p>ただ、デザインされた機能が実際に使えるものになるとは限らない。自身でも失敗と認める機能(<a href="http://html5doctor.com/interview-with-ian-hickson-html-editor/">AppCacheやWeb Storage、History APIなど</a>)は少なくない。欲しいものではなかったことがわかった時にはもう遅いなんてことがあった。</p> <p>Hixieはdeclarativeな機能を好んでるふしがあって、それはたぶん<a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a>の独自性やオープンな競争を尊重してたからだと思うのだけど、同じ挙動というかなり強い互換性が求められる昨今にはあまり好かれるものではない。そういう反省もあってExtensible Webというのが来ていたりもするので、彼の設計思想がふんだんに反映されてるであろうHTMLをどれだけ綺麗に崩していけるかが、HTMLを発展させるポイントなのかなと。とはいえ彼を説き伏せるのはだいぶ至難の業だからねえ。</p> <p>ただ、HTML自体にどれくらい発展が求められているのかはちょっとわからない。新しい要素ならWeb Componentsで自分でやってねということになる(そうさせたい)だろうし、その他<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>はメンテしたりたまにちょっと足したり、他の仕様でさせるためのextension pointを作ったりするくらいで、基本的にはメンテナンスモードのままなのかもしれない。バージョンレスとは言ったけれど、バージョンを切るほどの活力はもうないのかなとも思う。</p> myakura Content ScriptsなChrome拡張をFirefox拡張に hatenablog://entry/8454420450093252365 2015-05-01T19:23:39+09:00 2015-10-16T07:10:56+09:00 追記(2015-10-16):WebExtensionsの発表 これを書いた数ヶ月後の8月21日、Mozillaが今後のアドオンをWebExtensionsというChrome拡張APIベースなものに移行していく計画を発表した。 The Future of Developing Firefox Add-ons | Mozilla Add-ons Blog WebExtensionsが正式発表 XUL/XPCOMベースのアドオンは将来的に非推奨へ - Mozilla Flux なので、今後のことを考えたりもともとの「Chrome拡張をFirefoxでも動かしたい」というのを考えるとWebExten… <h2><strong>追記(2015-10-16)</strong>:WebExtensionsの発表</h2> <p>これを書いた数ヶ月後の8月21日、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Mozilla">Mozilla</a>が今後のアドオンをWebExtensionsという<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>拡張<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>ベースなものに移行していく計画を発表した。</p> <ul> <li><a href="https://blog.mozilla.org/addons/2015/08/21/the-future-of-developing-firefox-add-ons/">The Future of Developing Firefox Add-ons | Mozilla Add-ons Blog</a></li> <li><a href="http://rockridge.hatenablog.com/entry/2015/08/23/003746">WebExtensionsが正式発表 XUL/XPCOMベースのアドオンは将来的に非推奨へ - Mozilla Flux</a></li> </ul> <p>なので、今後のことを考えたりもともとの「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>拡張を<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>でも動かしたい」というのを考えるとWebExtensionsベースなものにしたほうが良さそう。実際に試したところ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>拡張のmanifest.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>にWebExtensionsで必要なメンバを足しただけでふつうに動いたので、Content Scriptsベースな<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>拡張ならほとんど手間を書けずに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%ED%A5%B9%A5%D6%A5%E9%A5%A6%A5%B6">クロスブラウザ</a>な拡張にできそう。</p> <p>というわけで、このエントリで書いたAdd-on <a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a>ベースな拡張はいささかレガシーなものになりそうだけど、気になる方はお読みくださいな。</p> <hr /> <p>お手製のしょうもない<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>拡張を<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>拡張にしてみた。といってもタイトルにある通りContent Scripts、つまりユーザー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>レベルなものなので、そんな面倒ではなかった。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>拡張のContent Scripts</h2> <p>まずは同じコンセプトのものが<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>にあるのか、ドキュメントを探す。あった。</p> <ul> <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Guides/Content_Scripts">Content Scripts - Mozilla | MDN</a></li> </ul> <blockquote> <p>Many add-ons need to <a class="keyword" href="http://d.hatena.ne.jp/keyword/access">access</a> and modify the content of web pages. But the main add-on code doesn't get direct <a class="keyword" href="http://d.hatena.ne.jp/keyword/access">access</a> to web content. Instead, <a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a> add-ons need to factor the code that gets <a class="keyword" href="http://d.hatena.ne.jp/keyword/access">access</a> to web content into separate scripts that are called <em>content scripts</em>. This page describes how to develop and implement content scripts.</p> <p>Content scripts can be one of the more confusing aspects of working with the <a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a>, but you're very likely to have to use them. There are five <a class="keyword" href="http://d.hatena.ne.jp/keyword/basic">basic</a> principles:</p> <ul> <li>the add-on's main code, including "main.js" and other modules in "lib", can use the <a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a> high-level and low-level APIs, but can't <a class="keyword" href="http://d.hatena.ne.jp/keyword/access">access</a> web content directly</li> <li>content scripts can't use the <a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a>'s APIs (no <a class="keyword" href="http://d.hatena.ne.jp/keyword/access">access</a> to globals <code>exports</code>, <code>require</code>) but can <a class="keyword" href="http://d.hatena.ne.jp/keyword/access">access</a> web content</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a> APIs that use content scripts, like page-mod and tabs, provide functions that enable the add-on's main code to load content scripts into web pages</li> <li>content scripts can be loaded in as strings, but are more often stored as separate files under the add-on's "data" directory</li> <li>a message-passing <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> allows the main code and content scripts to communicate with each other</li> </ul> </blockquote> <p>拡張からページのDOMは直接触れられずContent Scripts経由というのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>と同じらしい。あとIsolated Worldというコンセプトも共通。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>の読み込み方は違いがあるけど、Content Scriptsのファイルはそのまま流用できそう(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>でしか対応してないものを使ってない限りは)。わーい。</p> <h3>jpm</h3> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>の場合はどうやら<a href="https://developer.mozilla.org/en-US/Add-ons/SDK">Add-on SDK</a>をインストールしないといけないらしい。これまではその<a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a>が<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>ベースのやつだったらしいんだけど、Fx38からNodeベースのjpmというものになったとのこと。</p> <ul> <li><a href="https://blog.mozilla.org/addons/2015/02/26/jpm-replaces-cfx-for-firefox-38/">JPM Replaces CFX For Firefox 38 | Mozilla Add-ons Blog</a></li> <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm">jpm - Mozilla | MDN</a></li> </ul> <p>というわけで <code>npm install -g jpm</code> でさくっとインストール後、<code>jpm init</code> で名前やらエンドポイントやらを設定。</p> <h3>Content Scriptsの読み込み</h3> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>拡張では manifest.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a> からContent Scriptを動作させたいURL(のパターン)とそのファイルを明示的に指定していた。</p> <pre><code>... "content_scripts": [ { "matches": [ "https://foo.bar/*" ], "js": [ "baz.js" ], "css": [ "quux.css" ] }, ... </code></pre> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>拡張の場合はエンドポイントのファイルを用意して、そこから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE%A5%D6%A5%EB">プログラマブル</a>な感じで指定するらしい。<code>jpm init</code>した場合は<code>index.js</code>ができる。</p> <p>今回の拡張はページに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>ファイルをぶっこむものなので、<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/page-mod">page-mod</a>という<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を使う。</p> <pre><code>const data = require('sdk/self').data const pageMod = require('sdk/page-mod') pageMod.PageMod({ include: "https://foo.bar/*", contentScriptFile: [ data.url('baz.js') ], contentStyleFile: [ data.url('quux.css') ] }) </code></pre> <h3>ファイルの置き場</h3> <p>エンドポイントを指定したら <code>jpm init</code> したディレクトリ直下にできたのだけれど、Content Scriptsのファイルとかはその中に <code>data</code> ディレクトリを作ってそこに置かないといけないらしい。ここで少しはまった。initしたら作ってほしいな。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>拡張はとくにディレクトリわけとかしてなかったので、そのまま読み込めないか試すもアウト。どうやらファイルを指定したとこで使った<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/self#data"><code>self.data.url()</code></a>は <code>data</code> ディレクトリ内のファイルのみしか読めないらしい。まじか…</p> <p>気になったので<a href="https://github.com/mozilla/addon-sdk/blob/master/lib/sdk/self.js">ソース</a>を見てみる。</p> <pre><code>exports.data = Object.freeze({ url: uri, load: function read(path) { return readURISync(uri(path)); } }); </code></pre> <p>はいはい。では <code>uri</code> はというと…</p> <pre><code>const uri = (path="") =&gt; path.contains(":") ? path : addonDataURI + path.replace(/^\.\//, ""); </code></pre> <p>ええ。それで <code>addonDataURI</code> はというと、</p> <pre><code>const addonDataURI = baseURI + "data/"; </code></pre> <p>(´Д`)</p> <p>固定だ…ちょうmagicだ……</p> <p>というわけであきらめかけてたんだけど、ふと <code>data.url('../hoge.js')</code> としてみたら読み込めた。でもいいのかな…まあ動かなくなったら考えよう。</p> <p>ディレクトリ固定、もやっとすることはあるけど拡張のレビューとか、他のひとの拡張を知りたいときには見るところが決まっていて便利なのだろうなとも思う。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>だとmanifest.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>見ないといけないし。</p> <h3>その他</h3> <p>作った拡張は <code>jpm xpi</code> でパッケージ化すれば再起動不要なアドオンとしてインストールできる。</p> <p>Content Scriptレベルならふつーにできたけど、UIになにかぶっこむとかそういうのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>がだいぶ違うので、できるだけモジュールに落とすとかしないと共通部分が減るばかりな気がした。試したいんだけどそういう拡張を作ったことがない(…)ので、なんかア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>を持とう。</p> myakura FirefoxのCSS Unprefixing Service hatenablog://entry/8454420450092534720 2015-04-24T21:18:49+09:00 2016-09-23T22:39:32+09:00 追記(2016-09-23):-webkit-接頭辞のサポートを一部のサイトのみ対象とする方針はその後方針転換し、すべてのサイトを対象とすべく必要な機能やエイリアスの実装が行われ、Firefox 49でリリースされた。 Webkit! RESOLVED FIXED - otsukare Firefox 49 fixes sites designed with WebKit in mind, and more ★ Mozilla Hacks – the Web developer blog 標準での対応については、もととなる機能を標準化したうえでCompatibility Standardでエイ… <p><strong>追記(2016-09-23)</strong>:<code>-webkit-</code>接頭辞のサポートを一部のサイトのみ対象とする方針はその後方針転換し、すべてのサイトを対象とすべく必要な機能や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%A4%A5%EA%A5%A2%A5%B9">エイリアス</a>の実装が行われ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a> 49でリリースされた。</p> <ul> <li><a href="http://www.otsukare.info/2016/01/04/webkit-resolved-fixed">Webkit! RESOLVED FIXED - otsukare</a></li> <li><a href="https://hacks.mozilla.org/2016/09/firefox-49-fixes-sites-designed-with-webkit-in-mind-and-more/">Firefox 49 fixes sites designed with WebKit in mind, and more ★ Mozilla Hacks – the Web developer blog</a></li> </ul> <p>標準での対応については、もととなる機能を標準化したうえで<a href="https://compat.spec.whatwg.org/">Compatibility Standard</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%A4%A5%EA%A5%A2%A5%B9">エイリアス</a>を定義している。ただ<code>webkitMatchesSelector()</code>や<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a> Animationsのイベントなどは、DOM仕様に組み込まれていたりも。</p> <p>というわけで、ここで取り上げた<code>layout.css.unprefixing-service.enabled</code>は意味をなさなくなる。接頭辞の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%A4%A5%EA%A5%A2%A5%B9">エイリアス</a>なしでも動くかどうかは、<code>layout.css.prefixes.webkit</code>という設定が<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>については用意されている。</p> <hr /> <p>先日about:configに<code>layout.css.unprefixing-service.enabled</code>なんてのを見つけて「なんだろう」と思ってたのだけど、Compatibility Teamの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E1%A1%BC%A5%EA%A5%F3%A5%B0%A5%EA%A5%B9%A5%C8">メーリングリスト</a>にアナウンスがあった。どうやら<code>-webkit-</code>な<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>プロパティとかがあったら、それを標準のコードとして解釈するものらしい。</p> <ul> <li><a href="https://groups.google.com/forum/#!topic/mozilla.compatibility/zC5pjiV3gn0">CSS Unprefixing Service enabled in Nightly 39 (and riding the trains), for whitelisted sites</a></li> </ul> <blockquote>This feature is only active for the "top 10" broken Chinese mobile sites that Peipei provided[1] (e.g. several Baidu services and m.taobao.com). The whitelisted sites should have a much-improved user experience, due to <a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a> converting legacy -<a class="keyword" href="http://d.hatena.ne.jp/keyword/webkit">webkit</a> prefixed <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a> into equivalent unprefixed <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>.</blockquote> <p><a href="http://myakura.hatenablog.com/entry/2012/08/14/020029">Mozillaは2012年にもWebKit接頭辞について検討</a>していて、当時は<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>だけでは意味がないと判断していた。ただ<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox%20OS">Firefox OS</a>端末の投入とかで状況が多少変わったんだろうか。それとも<a class="keyword" href="http://d.hatena.ne.jp/keyword/UA">UA</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Sniffing">Sniffing</a>や<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>についても似たようなことやってるのかな?</p> <p>まだサービスの実装も途中らしく、Gradientsや<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a> Animationsはサポートされてないとのこと。<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a> Animationsについては<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1132754#c0">Yahoo! JAPANもWebKitのみらしく、このままだと登録しないとかもね</a>なんて話が出ている。ヤフーさん!!!Yトップなんとか!!</p> <p>PrestoやProject Spartanではすべてのサイトを対象に接頭辞の処理をしている(みたいだ)けど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Mozilla">Mozilla</a>の場合は<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1132745">特定サイトのみに限定させる</a>みたい。特定サイトだけの対応は<a class="keyword" href="http://d.hatena.ne.jp/keyword/IE">IE</a>のCompatibility Listの膨れっぷりを見ると茨の道な気もするけれど、がんばってほしい。</p> myakura SassScriptでリスト関数を拡張する hatenablog://entry/8454420450084373022 2015-02-20T01:26:29+09:00 2015-02-20T01:26:29+09:00 その昔Sassに凝っていたころに書いたメモを見つけた。供養のために公開。 当時のSassにはセパレータ判別の関数とかなかったので、今は特に必要ないものもあるね。時間経ったね。 グラデーションのmixinを書いたときに「リストを扱う関数が足りないなあ」と思ったので、関数をいろいろ書いてみている、RubyじゃなくSassで。 is-list($arg) リストかどうかを返す関数。list 型のほか、可変長引数の arglist 型でも true を返す。 @function is-list($arg) { @return type-of($arg) == 'list' or type-of($ar… <p>その昔Sassに凝っていたころに書いたメモを見つけた。供養のために公開。</p> <p>当時のSassにはセパレータ判別の関数とかなかったので、今は特に必要ないものもあるね。時間経ったね。</p> <hr /> <p>グラデーションのmixinを書いたときに「リストを扱う関数が足りないなあ」と思ったので、関数をいろいろ書いてみている、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>じゃなくSassで。</p> <h2><code>is-list(<code>$arg</code>)</code></h2> <p>リストかどうかを返す関数。<code>list</code> 型のほか、可変長引数の <code>arglist</code> 型でも <code>true</code> を返す。</p> <pre>@function is-list($arg) { @return type-of($arg) == 'list' or type-of($arg) == 'arglist'; } </pre> <p>ただこれ、ちょっと問題があって、<code>('item')</code> などひとつの値を括弧でくるんだものを渡すと <code>false</code> を返してしまう。</p> <pre>$list: ('item'); @debug is-list($list); // DEBUG: false </pre> <p>上の場合 <code>$list</code> は <code>string</code> 型になって結果 <code>false</code> になる。なんでかというと、<a href="https://github.com/nex3/sass/issues/679#issuecomment-14534399">Sassでは括弧がリストのデリミタではない</a>ので、括弧で包んでもリストにならないから。えー……</p> <p>ただ、もし括弧をデリミタにすると、演算の優先順位を変える括弧と区別がつけられず、<code>(3 + 4) * 5</code> という式が「<code>3 + 4 → 7</code> という値の入ったリストに5を掛けている」など解釈されてしまう。ううむ……</p> <p>ただ、それはそれで困ったもので <code>nth()</code> や <code>index()</code> にリストを突っ込んだつもりがアイテムがひとつだったためエラーになったりした。幸い、この前リリースされたSass 3.2.7でリスト関数についてはアイテムがひとつでもリストとして解釈されるように修正されたのでよかったんだけれど、<code>type-of()</code> の挙動は引き続き変わっていない。まあ、仕様なのでちょっと諦める。</p> <h3>余談:アイテムひとつのリストを作る方法</h3> <p>アイテムひとつのリストを作れないわけではない。空のリストをつくって、そこにアイテムをいっこ加えればよい。こうやって作ったリストは型がちゃんと <code>list</code> になる。</p> <pre>$oneitemlist: append((), 'item'); @debug type-of($oneitemlist); // DEBUG: "list" </pre> <h2><code>contains(<code>$list</code>, <code>$value</code>)</code></h2> <p>ある値がリスト内にあるかどうかを返す関数。</p> <pre>$fruits: '<a class="keyword" href="http://d.hatena.ne.jp/keyword/apple">apple</a>' 'banana' 'cherry'; @debug contains($fruits, 'banana'); // DEBUG: true </pre> <p>実装は <code>index()</code> を使っている。</p> <pre>@function contains($list, $value) { @if not is-list($list) { @warn 'argument <a class="keyword" href="http://d.hatena.ne.jp/keyword/error">error</a>: #{$list}'; @return '<a class="keyword" href="http://d.hatena.ne.jp/keyword/error">error</a>'; } @return type-of(index($list, $value)) == 'number'; } </pre> <p><code>index()</code> だけで済みそうなものだけど、Sassの <code>index()</code> は値が見つかない場合に <code>false</code> を返すので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>でやるような <code>indexOf(<var>item</var>) &gt; -1</code> みたいなのができない。なので <code>type-of()</code> を使い <code>index()</code> が数値を返すかで判定している。</p> <h2><code>has(<code>$value</code>, <code>$in</code>)</code></h2> <p><code>has()</code>はただ、<code>contains()</code>引数の順序が替わっただけ。内部的には <code>contains()</code> を使ってる。</p> <pre>@function has($value, $in) { @return contains($in, $value); } </pre> <pre>$oyatsu: 'umaibou' 'miyako-konbu' 'big-katsu'; @debug has('banana', $oyatsu); // DEBUG: false </pre> <p>Sass組み込みのリスト関数は第一引数にリストを取るような設計なんだけど、mixinとかfunctionを書いてると、リストではなく値を前に出したほうがコードが読みやすくなるなと思ったことが結構あったので書いてみた。</p> <p>あと、<code>has()</code>は引数のキーワードを変えている。これでどうなるかというと、ちょっとヒューマンリーダブル感が出る感じに書ける。</p> <pre>$oyatsu: 'umaibou' 'miyako-konbu' 'big-katsu'; @if has('banana', <strong>$in: $oyatsu</strong>) { content: 'わーい'; } </pre> <p>む、書いてみたけど、そんな分り易くないというか、読みにくくなってるだけかも……</p> <h2><code>separator(<code>$list</code>)</code></h2> <p>Sassのリストはカンマ区切り、空白区切りと、ふたつの書き方がある。そのどっちを使っているか検出する関数。</p> <pre>@function separator($list) { @if not is-list($list) { @warn 'argument <a class="keyword" href="http://d.hatena.ne.jp/keyword/error">error</a>: #{$list}'; @return '<a class="keyword" href="http://d.hatena.ne.jp/keyword/error">error</a>'; } @if length($list) == 1 { @return null; } $list_comma: (); $list_space: (); @each $item in $list { $list_comma: append($list_comma, $item, comma); $list_space: append($list_space, $item, space); } @if $list == $list_comma { @return 'comma'; } @else if $list == $list_space { @return 'space'; } @else { @return '<a class="keyword" href="http://d.hatena.ne.jp/keyword/error">error</a>'; } } </pre> <p>アイテムとその並びが同じでも、セパレータが違うと同一とみなされないことを利用している。</p> <pre>@debug (1, 2, 3) == (1 2 3); // DEBUG: false </pre> <p>中身は同じでセパレータが違う2つのリストを <code>append()</code> しまくってつくってるので、実行コストが多分高い。</p> <h2><code>reverse(<code>$list</code>, <em class="optional"><code>$separator</code></em>)</code></h2> <p>項目が逆に並んだリストを作る。オプションでセパレータを変更可能。</p> <pre>@function reverse($list, $separator: null) { @if not is-list($list) { @return $list; } @if not has($separator, (space comma)) { $separator_orig: separator($list); @if has($separator_orig, (space comma)) { $separator: $separator_orig; } @else { $separator: space; } } $i: length($list); $result: (); @while $i &gt; 0 { $result: append($result, nth($list, $i), $separator); $i: $i - 1; } @return $result; } </pre> <p>セパレータを変更可能にする必要なんて(たぶん)ないのだけど、もとのセパレータ知らないと返すリストのセパレータをどうすればいいか悩む→セパレータ検出しよう→じゃあ変更オプションもつけようか的な。こうして無駄な機能が増えていくのだろう……</p> <h2><code>is()</code> ― なんでも系</h2> <p>引数のキーワードでヒューマンリーダブルにしよう計画をやっていてひらめいた。こんなのはどうだろう。</p> <pre>@function is($args_list) { $value: nth($args_list, 1); $keyword: nth($args_list, 2); $target: nth($args_list, 3); @if $keyword == 'in' { @return contains($target, $value); } } </pre> <p>こう使える。</p> <pre>$fruits: '<a class="keyword" href="http://d.hatena.ne.jp/keyword/apple">apple</a>' 'banana' 'cherry'; @debug is('banana' in $fruits); // DEBUG: true </pre> <p>関数の引数を「スペース区切りのリストひとつ」として扱って、引数を自然文ちっくに書けるようにしている。引数の数は固定しといて、キーワードに応じて処理を振り分ける。キーワードを増やせば拡張可能。</p> <pre>@function is($args_list) { ... @if $keyword == 'in' { @return contains($target, $value); } @if $keyword == 'typeof' { @return type-of($value) == $target; } @if $keyword == 'not' { @return $value != $target; } </pre> <p><code>is(<var>A</var> not <var>B</var>)</code> が要るかどうかはさておき、こんな感じに拡張可能。</p> <hr /> <p>という書きかけでした。ほんとはもうちょっと考えてたはずなんだけど忘れてしまった。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>ではなくSassでというの、当時はアレ感しかない(まあ今もそうか)けど、libsassの隆盛で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>での拡張がちょっとという感じもあるし、本体側の拡張よりもSassScriptでできたほうが今後はいいのかもなと少し思った。速く動くのかどうかは知らないけれど。</p> myakura Android Wearを半年使ってみたので雑感 hatenablog://entry/8454420450078552728 2014-12-31T16:03:06+09:00 2014-12-31T16:03:06+09:00 Google I/OでLG G Watchを手に入れてから半年、Android Wearの感想を改めて。使って1ヶ月後に書いたGoogle+の投稿と変わらないところもあるけど。 腕時計を再発見する LG G Watchを手に入れるまで、10年くらい腕時計をしていなかった。ケータイもあったし、どこかに時計はあったし。腕になにかついているのは煩わしいとも思っていた。 つけてみると、あらけっこう便利。ケータイを出さなくても、どこかにあるだろう時計を探さなくても、左腕をくいっとすれば時間が見られる。 腕時計をつけている煩わしさはある。パソコンでなにか作業しているときは外している。あと夏場は腕時計の裏に… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20I/O">Google I/O</a>でLG G Watchを手に入れてから半年、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a> Wearの感想を改めて。使って1ヶ月後に書いた<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%2B">Google+</a>の投稿と変わらないところもあるけど。</p> <h2>腕時計を再発見する</h2> <p>LG G Watchを手に入れるまで、10年くらい腕時計をしていなかった。ケータイもあったし、どこかに時計はあったし。腕になにかついているのは煩わしいとも思っていた。</p> <p>つけてみると、あらけっこう便利。ケータイを出さなくても、どこかにあるだろう時計を探さなくても、左腕をくいっとすれば時間が見られる。</p> <p>腕時計をつけている煩わしさはある。パソコンでなにか作業しているときは外している。あと夏場は腕時計の裏に汗をかいて、ああこういうものだったなあと思いだした。</p> <p>慣れてきて外出時は毎回つけて、それなりに便利かなと思っていたのだけれど、最近あることに気づいた。寒くなって袖の長いものを着ると、まくらないといけなくてちょっと煩わしい。それだけならまだいいんだけど、冬になってニットやコートなどまくりにくいものを着るようになると、ポケットからNexus 5を出したり、周りの時計を探したりするほうが楽になった。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a> Wear</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a> Wear端末は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%BF%A5%F3%A5%C9%A5%A2%A5%ED%A5%F3">スタンドアロン</a>なものではなく、ペアリングする<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>端末が必要。なのでI/Oでも、使ってるのが<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>だからアクティベートできないという人がかなりいた。あとは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>のバージョンも4.3以降とかで、使えない<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>端末を持ってたひとも多かった。Nexus 5も配ってほしかったです!!!</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Apple">Apple</a> Watchも<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>が必要だけれど、それを知らない<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>ユーザーが買っちゃったりしないかね。販売員は大変なのではないか。</p> <h2>Notificationと<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Nowの端末</h2> <p>できること。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>のNotificationを腕元で見られる・多少それに対して反応できる端末という感じ。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Gmail">Gmail</a>やLINEならメッセージの内容も読めたりするけど、行あたりの文字数が少ないので、長いメールだとつらい。</p> <p>あとは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Nowの情報を適当なタイミングで手元に知らせてくれるので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A1%BC%A5%C8%A5%D5%A5%A9%A5%F3">スマートフォン</a>よりもコンテクスチュアルかも。</p> <p>ただ自分はNotificationやらがあまり好きではなく、けっこう切っていたりするので、通知ばんばんなひとよりは恩恵を受けてないのかも。</p> <h2>インプットはそんなできない</h2> <p>タッチパネル対応だけど、タッチによる文字入力とかは標準状態ではできない。任意の情報を入力したければ音声検索になる。</p> <p>最初は面白がって使っていたのだけど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A1%BC%A5%C8%A5%D5%A5%A9%A5%F3">スマートフォン</a>や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%D6%A5%EC%A5%C3%A5%C8">タブレット</a>でもふだん音声検索をそんな使わない(目覚ましセットくらいかなあ)ので、こちらもあまり恩恵に預かれていない。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A1%BC%A5%C9%A5%D1%A1%BC%A5%C6%A5%A3">サードパーティ</a>のアプリを入れると文字入力やらゲームやらはできるけど、小さい画面をこねこねしまくるのはね…あまりかっこよくないよね。 あとあぶない。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A1%BC%A5%C8%A5%D5%A5%A9%A5%F3">スマートフォン</a>でもけっこう周りがみえなくなるのに、さらに小さい画面なのでほんとに周りがみえない。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Apple">Apple</a> Watchはけっこう画面をこねこねしそうな感じだけど、大丈夫なのかな。</p> <h2>LollipopでのPhone+Wear連携</h2> <p>出た当初の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>は4.4.xだったのだけれど、この状態で使うのは不便だった。</p> <p>Wearのカードには、詳細を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A1%BC%A5%C8%A5%D5%A5%A9%A5%F3">スマートフォン</a>で開くメニューが出るものがある。ただ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A1%BC%A5%C8%A5%D5%A5%A9%A5%F3">スマートフォン</a>のロックを解除しないといけないので、Wearから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A1%BC%A5%C8%A5%D5%A5%A9%A5%F3">スマートフォン</a>のアプリ起動操作→<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A1%BC%A5%C8%A5%D5%A5%A9%A5%F3">スマートフォン</a>取り出す→ロック解除というステップを踏むのでシームレスにつながってる感がまったくなかった。</p> <p>Lollipopになって、指定した<a class="keyword" href="http://d.hatena.ne.jp/keyword/Bluetooth">Bluetooth</a>機器が近くにあればスワイプだけでロック解除できるようになった。ステップ数は変わらないけど、それなりにつながってる感はでた。ロックまで自動で解除してくれたらなとは思う。</p> <h2>電池がもたない</h2> <p>腕時計だと数年電池がもつような気がするけれど、Wear端末はBattery400mAhとかそこらなので、2日に一度は充電しないといけないのがつらい。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Apple">Apple</a> Watchも多少は長持ちしそうだけど、でも腕時計に比べるとだいぶいけてない。</p> <p>充電も、LG G Watchは専用<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EC%A1%BC%A5%C9%A5%EB">クレードル</a>にしかUSBの端子がないので、それを忘れると充電できずだいぶつらい。Qiとかに対応してるものだといいけれど、それでも頻繁に充電しないといけないので煩わしい。もうちょっとなんとかなるといいけれど…</p> <p>悪い中でも良い点というのは、電池の容量が小さいので充電にかかる時間が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A1%BC%A5%C8%A5%D5%A5%A9%A5%F3">スマートフォン</a>とかに比べて短いところ。</p> <h2>Web感はまだない</h2> <p>ようやくWebの話に持ってこられた。</p> <p>画面が小さいとブラウザもなにもという感じなので、あまりWebとどうこうする感じはない。</p> <p>技術的にも、Service Workersが<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>に入り始めたところで、Web Push <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>やWeb Notifications <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>のSW拡張はこれから。来年の今頃くらいには<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>でshipしてたりするのかな。GeofencingもGeolocation WGでやるようなので、それもくるとWebが少し絡んできそう。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B9%A5%B1%A1%BC%A5%B9">ユースケース</a>としてはどんなものがあるだろう。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A1%BC%A5%C8%A5%D5%A5%A9%A5%F3">スマートフォン</a>でWebサイトにアクセスしてSWがインストールされれば、(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D1%A1%BC%A5%DF%A5%C3%A5%B7%A5%E7%A5%F3">パーミッション</a>がらみでステップが増えるだろうけれど)、いろんなことをフックにWebからWear端末に通知できるようになる。</p> <p>Webサイトへのアクセスがアプリに勝るケース…イベントごととかかなあ。あとは、ショッピングモールとかだろうか。Webにアクセスさせる動線を設計しないといけないけど、アプリのインストールよりは気軽にしてもらえるのではないか。</p> <p>他にもWeb技術でできることが増えてくるとよいね。ではよいお年を。</p> myakura Firefoxおめでとう&みんな開発版つかおうよ hatenablog://entry/8454420450073358757 2014-11-13T00:07:50+09:00 2014-11-13T00:07:50+09:00 Firefox 1.0のリリースから10年経った。おめでとうございます。 リリース前のことだけど、WikipediaのFirefoxの記事をちょこちょこいじっていて、FirebirdからFirefoxに名前が変わった件について「Firebirdプロジェクト側から攻撃を受け〜」というふうな感じで書いたら、誰かに表現がきついと言われたことを思い出した。ちぇっ。 Firefox Developer Edition さてそんな記念日にFirefox Developer Editionがリリースされた。 Mozilla Introduces the First Browser Built For Dev… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a> 1.0のリリースから10年経った。おめでとうございます。</p> <p>リリース前のことだけど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Wikipedia">Wikipedia</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>の記事をちょこちょこいじっていて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firebird">Firebird</a>から<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>に名前が変わった件について「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firebird">Firebird</a>プロジェクト側から攻撃を受け〜」というふうな感じで書いたら、誰かに表現がきついと言われたことを思い出した。ちぇっ。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a> Developer Edition</h2> <p>さてそんな記念日に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a> Developer Editionがリリースされた。</p> <ul> <li><a href="https://hacks.mozilla.org/2014/11/mozilla-introduces-the-first-browser-built-for-developers-firefox-developer-edition/">Mozilla Introduces the First Browser Built For Developers: Firefox Developer Edition</a></li> </ul> <p>Aurora channelというBetaより一段階前のもののリ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D6%A5%E9%A5%F3%A5%C7%A5%A3%A5%F3%A5%B0">ブランディング</a>なので、いまのところそんな違いはない気がする。ただ<a class="keyword" href="http://d.hatena.ne.jp/keyword/Mac">Mac</a>でゴニョゴニョしなくても並行起動できる<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>ができたのはうれしい。</p> <p>テーマが黒くて見づらかったのだけれど、Developer Toolsの設定を開いてテーマをLight themeにしたら見やすくなった。</p> <p>今後開発者向けの機能がこれだけに入るというの増えるのかな。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>も<a class="keyword" href="http://d.hatena.ne.jp/keyword/Opera">Opera</a>も<a class="keyword" href="http://d.hatena.ne.jp/keyword/IE">IE</a>もとくにそういうのしてなかった気がするので、そうなるとちょっとユニークでおもしろいかも。</p> <h2>リリースチャンネルまでの長い期間をどうするか</h2> <p>David Baronがリリースサイクルについて書いていた。</p> <ul> <li><a href="http://dbaron.org/log/20141106-release-cycles">A possible approach to shorter release cycles</a></li> </ul> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>のリリースサイクルは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a> 5くらいから6週間でチャンネルを移るようになっている。チャンネルはNightly→Aurora→Beta→Releaseの4つ。なので、Nightlyに入った変更や機能追加がリリースに入るまでに18週かかることになる。4, 5ヶ月。長い。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>はというと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromium">Chromium</a> (→) Dev→Beta→Stableという感じ。ブランチが切られてしばらく<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromium">Chromium</a>とDevのバージョンが離れるけど、基本的には一緒なので<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>よりも新しい機能が6週短く入る。3ヶ月くらいになるのかな。</p> <p>よりNightlyに近いチャンネルのユーザー数は少ないし、リリースまでに長いので追加した機能が実際に使われるまでが遅くなって、それで起こったバグへの対処が遅くなる。なのでなんとかしたいらしい。</p> <p>といっても、単純にチャンネルをひとつなくすというア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>については、ブランチが切れる間際に入ったものとかはまだリリースクオリティに達していないこともあるという話があるらしい。Aurora→Betaを経てよくするという癖ができてるということなのかな。</p> <p>で、Betaを「ブランチしてから1週はRelease、以降はAuroraにする」という案をdbaronが出している。Beta内で参照する<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%DD%A5%B8%A5%C8%A5%EA">レポジトリ</a>(安定性)を2段階にすると。こうなると、Nightly→だいたいAuroraな新チャンネル→Releaseとなる。Beta使ってる人はそれなりにいるっぽいので、これだと新しい機能へのフィードバックもそれなりにできそうと。ふむ。</p> <p>案だけという話なのでどうなるかはわかんない。あとDeveloper Editionとの絡みも不明。でも短くなるといいなあ(ウォッチャー的にも)。</p> <h2>みんな開発版つかわないかい</h2> <p>フィードバックが欲しいというのはどのベンダーでも持っているようで、TPACやBlinkOnでも試験的な機能をベンダー接頭辞の反省を活かしどう安全に提供するかというセッションをやっていた。</p> <p>Web開発やってる人が、リリース直後にバグでわんわん言うのはなんだか嘆かわしい。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>はプロファイルマネージャを使えば<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%A3%BF%F4">複数</a>のチャンネルを並行起動できるし、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>の場合は<a href="https://www.google.com/chrome/browser/canary.html">Canary</a>がある。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>, <a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>は6週間で新しいものに置き換わる。いま作ってるものがローンチする時期が、いまDevなチャンネルなものがリリースに移る時期になることってけっこうあるのではないか。開発版だと開発中だからというバグもあるけど、より<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CA%A5%A4%A5%C8%A5%EA%A1%BC">ナイトリー</a>に近いもの使うことで事前に防げるものもあるだろうし、ブラウザ作る側にも少なからずヘルプになるので、悪くないと思うんだけどなあ。</p> myakura <picture>まわり雑感 その1 hatenablog://entry/8454420450070899639 2014-10-31T09:07:18+09:00 2014-10-31T09:07:18+09:00 Chrome 38が出て<picture>が有効になったので、いくつか記事を訳した。 レスポンシブイメージのネイティブサポート - HTML5 Rocks Dev.Opera — ネイティブサポートされたレスポンシブ・イメージ Dev.Opera — レスポンシブ・イメージ:ユースケースと入門用のコードサンプル HTML5 Rocksのは<picture>の簡単な使い方をざっと紹介。Dev.Operaのネイティブうんぬんは<picture>と<img srcset>, <img sizes>を細かく説明。もひとつのDev.Operaのサンプルのやつはユースケースごとに組み合わせをいろいろ書いた… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a> 38が出て<code>&lt;picture&gt;</code>が有効になったので、いくつか記事を訳した。</p> <ul> <li><a href="http://www.html5rocks.com/ja/tutorials/responsive/picture-element/">レスポンシブイメージのネイティブサポート - HTML5 Rocks</a></li> <li><a href="https://dev.opera.com/articles/ja/native-responsive-images/">Dev.Opera — ネイティブサポートされたレスポンシブ・イメージ</a></li> <li><a href="https://dev.opera.com/articles/ja/responsive-images/">Dev.Opera — レスポンシブ・イメージ:ユースケースと入門用のコードサンプル</a></li> </ul> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/HTML5">HTML5</a> Rocksのは<code>&lt;picture&gt;</code>の簡単な使い方をざっと紹介。Dev.<a class="keyword" href="http://d.hatena.ne.jp/keyword/Opera">Opera</a>のネイティブうんぬんは<code>&lt;picture&gt;</code>と<code>&lt;img srcset&gt;</code>, <code>&lt;img sizes&gt;</code>を細かく説明。もひとつのDev.<a class="keyword" href="http://d.hatena.ne.jp/keyword/Opera">Opera</a>のサンプルのやつは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B9%A5%B1%A1%BC%A5%B9">ユースケース</a>ごとに組み合わせをいろいろ書いたサンプル。それぞれ少しずつ違っている。おすすめは2つ目。ちょっと長いけど、書いているのがBlink, <a class="keyword" href="http://d.hatena.ne.jp/keyword/WebKit">WebKit</a>で<code>&lt;picture&gt;</code>とかを実装しているYoavなので。</p> <p>以下いろいろ。</p> <h2>だいたい<code>&lt;img srcset&gt;</code>で事足りる気がする</h2> <p>要素ということもあって<code>&lt;picture&gt;</code>に目が向きがちだけれど、“<a href="http://blog.cloudfour.com/dont-use-picture-most-of-the-time/">Don’t use <picture> (most of the time)</picture></a>”などで言われているとおり何が何でも<code>&lt;picture&gt;</code>つかえというわけではない。</p> <p>使うのは<code>&lt;img srcset&gt;</code>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Retina">Retina</a>対応(<code>x</code> デスクリプタ使うやつ)が多いのではないか。他の属性やら<code>&lt;picture&gt;</code>はResponsive Web Designでの利用が多そうだけれど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Retina">Retina</a>対応はRWD関係なくやりたいことだろうから。</p> <p>なので基本的にはこんなコードでよさそう。<code>2x</code>な画像を書いた<code>srcset</code>をつけるだけという。</p> <pre>&lt;img srcset="image-2x.<a class="keyword" href="http://d.hatena.ne.jp/keyword/png">png</a> 2x" src="image.<a class="keyword" href="http://d.hatena.ne.jp/keyword/png">png</a>" alt="..."&gt; </pre> <p>ただ<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>さまが3xになったので、3xな画像を…といきっちゃうかもしれない。そしたらこうだ。</p> <pre>&lt;img srcset="image-2x.<a class="keyword" href="http://d.hatena.ne.jp/keyword/png">png</a> 2x, image-3x.<a class="keyword" href="http://d.hatena.ne.jp/keyword/png">png</a> 3x" src="image.<a class="keyword" href="http://d.hatena.ne.jp/keyword/png">png</a>" alt="..."&gt; </pre> <p>画像リソースの数は増えるけれど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%AF%A5%A2%A5%C3%A5%D7">マークアップ</a>が複雑になったとはまだ言わなくてもいいレベルではないか…な。</p> <h3>3xいるのかね</h3> <p>さて、3x。そんなに要らないのではないかと思っている。というのは1x→2xほどのぼけ具合がないから(個人の感想です)。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>は昨年秋から3x時代に入ってるのだけれど、アプリのアイコンやアセットで3xなものがあるのはまだ多くない。たとえばLINEとか、スタンプがうっすらぼやけたりしている。 とはいえアプリの対応とかは<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>が牽引している感があるので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a> 6 Plusが発売されたいま、3xな画像が増えてくるのかなとも思う。</p> <p>でもね…あまりにもバリエーションが増えすぎてしまうと作成や管理の面でもえらく大変になるだろうし、3xや4xが出たからといって純朴に対応しているとすりきれてしまうのではないか。</p> <p>軽く調べた感じだと、いまのところ<a class="keyword" href="http://d.hatena.ne.jp/keyword/Apple">Apple</a>も<a class="keyword" href="http://d.hatena.ne.jp/keyword/apple">apple</a>.comで3xな画像を出していない。<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a> 6 Plusは3xといっても、<a href="http://www.paintcodeapp.com/news/iphone-6-screens-demystified">幅1242pxな画面を1080pxに縮小して表示</a>とすごいことになってるので、単純に2xのアセットを3xで表示した見た目になるわけではない。なのでぼけ度合いは2xなものを3xでというものよりは多少よいのかもしれない。</p> <h2><code>&lt;img&gt;</code>ではコントロールできない</h2> <p><code>srcset</code>や<code>sizes</code>で指定する画像はあくまで「ヒント」なので、「意図とは違った画像が表示されるかも」というのは頭の片隅に置いとくといいかもしれない。</p> <p>たとえば「重いし<a class="keyword" href="http://d.hatena.ne.jp/keyword/Retina">Retina</a>なんかいらねえよ」みたいなオプションが設定についたり、ブラウザがそこら辺賢くなってくれたりすると(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Opera">Opera</a>とかやりそうな気がする)、2x/3xなディスプレイでも1xな画像を出しちゃうなんてことが起こるだろう。</p> <p>最近だとBlinkで、リサイズ時にすでに高解像度の画像がある場合は、candidateが変化してもそれをダウンロードしなくなった。軽くバグな気もするけれど……</p> <h3><code>&lt;picture&gt;</code>+<code>&lt;source&gt;</code>でコントロールできなくもない</h3> <p>「コントロールできないのはちょっと…」というケースはあまりあってほしくないけれどあるかもしれない。<code>&lt;picture&gt;</code>と<code>&lt;source&gt;</code>を使えば、コントロールさせることも一応できる。<code>&lt;source&gt;</code>はヒントではなく「命令」になるからだ。</p> <p>たとえば、2xには2xな画像を、3xには3xなそれを確実に提供したい場合はこうなるだろう。</p> <pre>&lt;picture&gt; &lt;source media="(min-resolution: 3dppx)" srcset="image-3x.<a class="keyword" href="http://d.hatena.ne.jp/keyword/png">png</a>"&gt; &lt;source media="(min-resolution: 2dppx)" srcset="image-2x.<a class="keyword" href="http://d.hatena.ne.jp/keyword/png">png</a>"&gt; &lt;img src="image.<a class="keyword" href="http://d.hatena.ne.jp/keyword/png">png</a>" alt="..."&gt; &lt;/picture&gt; </pre> <ul> <li><code>srcset</code>に画像をならべるのではなく、<code>&lt;picture&gt;</code>に<code>&lt;source&gt;</code>をならべる</li> <li><code>srcset</code>内の<code>3x</code>の代わりに<code>media</code>に<code>min-resolution: 3dppx</code>を使う</li> </ul> <p>1行でだいたい同じものが書けてたのにだいぶ大げさになった。Webでコントロールを求めればめんどくさくなるのだ、というのを暗に伝えたいのかもしれない。</p> <p>もちろん、art directionのように画像を意図どおりに切り替えたいというケースはある。それはちゃんと<code>&lt;picture&gt;</code>を使わないとだめだろう。でもそうでない場合はなるべく減らして、ブラウザに任せたほうが賢いかなと。</p> <hr /> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%AF%A5%A2%A5%C3%A5%D7">マークアップ</a>とスタイルのseparation of concernsあたりについても書こうと思ったのだけど、考えがまとまってないのでとりあえず。</p> myakura <script async>でJavaScriptの非同期読み込みを hatenablog://entry/8454420450068512942 2014-10-14T06:17:13+09:00 2014-10-14T06:17:13+09:00 JavaScriptファイルをスクリプトから非同期で読み込むパターンは古い、という話を目にしたのはもう半年前のこと。 言ったのはIlya Grigorik。月末のGoogle Japanでのイベント、月初のHTTP2ConferenceにくるWebパフォーマンス界のすごいひとですよ。 Script-injected "async scripts" considered harmful - igvita.com 件のパターンは、スクリプトで動的に script を生成して、そこに読み込みたいJavaScriptファイルをぶっこんで読み込むというもの。 <script> var script = … <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>ファイルを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>から非同期で読み込むパターンは古い、という話を目にしたのはもう半年前のこと。</p> <p>言ったのはIlya Grigorik。<a href="http://googledevjp.blogspot.jp/2014/10/blog-post.html">月末のGoogle Japanでのイベント</a>、<a href="http://http2study.connpass.com/event/9209/">月初のHTTP2Conference</a>にくるWebパフォーマンス界のすごいひとですよ。</p> <ul> <li><a href="https://www.igvita.com/2014/05/20/script-injected-async-scripts-considered-harmful/">Script-injected "async scripts" considered harmful - igvita.com</a></li> </ul> <hr /> <p>件のパターンは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>で動的に <code>script</code> を生成して、そこに読み込みたい<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>ファイルをぶっこんで読み込むというもの。</p> <pre>&lt;script&gt; var script = document.createElement('script'); script.src = "//somehost.com/awesome-<a class="keyword" href="http://d.hatena.ne.jp/keyword/widget">widget</a>.js"; document.getElementsByTagName('head')[0].appendChild(script); &lt;/script&gt; </pre> <p>ところが、こうしてしまうと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>中のURL(ここでは <code>//somehost.com/awesome-widget.js</code>)がブラウザのプリロードスキャナにひっかからないこと、そしてこの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>の実行がCSSOMの構築を待つために、遅くなっちゃうんだと。</p> <p>で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/HTML5">HTML5</a>から導入された <code>&lt;script async&gt;</code> を使えば、非同期で読み込まれるし、プリロードスキャナの恩恵にも預かれるとのこと。サポート状況も良くなってきたので、そっち使ったほうがいいのではないかと。</p> <pre>&lt;script src="//somehost.com/awesome-<a class="keyword" href="http://d.hatena.ne.jp/keyword/widget">widget</a>.js" async&gt;&lt;/script&gt; </pre> <p>シンプル。古の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>読み込みが戻ってきた感。こういうハックなしにいいことできるようになってほしいよね。</p> <h2>ソーシャルボタンの読み込み部分を書き換える</h2> <p>さて、このIlyaのエントリが公開されてからしばらくして、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>で非同期読み込みをしていた<a href="https://developers.google.com/+/web/+1button/">+1ボタン</a>が <code>&lt;script async&gt;</code> を使うものに変わった。こんな感じになった。</p> <pre>&lt;!-- <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a> --&gt; &lt;script src="<a href="https://apis.google.com/js/platform.js">https://apis.google.com/js/platform.js</a>" async defer&gt;&lt;/script&gt; &lt;!-- ボタン --&gt; &lt;div class="g-plusone" data-annotation="none"&gt;&lt;/div&gt; </pre> <p>実質2行。シンプル。</p> <p>で、他のソーシャルボタン系も書き換えられないかと思ってやってみた。読み込むパターンはだいたい同じなので、そんな大した労力ではないはず。</p> <h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/Facebook">Facebook</a></h3> <pre>&lt;div id="fb-root"&gt;&lt;/div&gt; &lt;script&gt;(function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "//connect.<a class="keyword" href="http://d.hatena.ne.jp/keyword/facebook">facebook</a>.net/en_US/<a class="keyword" href="http://d.hatena.ne.jp/keyword/sdk">sdk</a>.js#xfbml=1&amp;version=v2.0"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', '<a class="keyword" href="http://d.hatena.ne.jp/keyword/facebook">facebook</a>-jssdk'));&lt;/script&gt; </pre> <p>こうなった。</p> <pre>&lt;script src="//connect.<a class="keyword" href="http://d.hatena.ne.jp/keyword/facebook">facebook</a>.net/en_US/<a class="keyword" href="http://d.hatena.ne.jp/keyword/sdk">sdk</a>.js#xfbml=1&amp;version=v2.0" id="<a class="keyword" href="http://d.hatena.ne.jp/keyword/facebook">facebook</a>-jssdk" async&gt;&lt;/script&gt; </pre> <p><code>&lt;div id="fb-root"&gt;&lt;/div&gt;</code> どうしようかなと思ったのだけど、なくても自動挿入されるので省いちゃった。</p> <h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a></h3> <pre>&lt;script&gt;!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'<a class="keyword" href="http://d.hatena.ne.jp/keyword/https">https</a>';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', '<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>-wjs');&lt;/script&gt; </pre> <p>こうなった。</p> <pre>&lt;script src="//platform.<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>.com/widgets.js" id="<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>-wjs" async&gt;&lt;/script&gt; </pre> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C8%A5%B3%A5%EB">プロトコル</a>を判別するコードは、protocol relativeなURLにした。</p> <h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%D6%A5%C3%A5%AF%A5%DE%A1%BC%A5%AF">はてなブックマーク</a></h3> <p><a href="http://b.hatena.ne.jp/guide/bbutton">ボタンのページ</a>見たら、すでに <code>&lt;script async&gt;</code> 使うようになってた。わーい。</p> <pre>&lt;script type="text/<a class="keyword" href="http://d.hatena.ne.jp/keyword/javascript">javascript</a>" src="<a href="http://b.st-hatena.com/js/bookmark_button.js">http://b.st-hatena.com/js/bookmark_button.js</a>" charset="<a class="keyword" href="http://d.hatena.ne.jp/keyword/utf-8">utf-8</a>" async="async"&gt;&lt;/script&gt; </pre> <h2>関数を使った読み込みも書き換えてみる</h2> <p>身の回りでそれ系のボタンを使うときは、「<a href="http://t32k.me/mol/log/social-button-bffs/">ソーシャルボタンはお友達さ(・ω — MOL</a>」にある非同期読み込みをする関数をベースにしたものを使っていた。</p> <pre>&lt;div id="fb-root"&gt;&lt;/div&gt; &lt;script&gt;(function(d, s) { var js, fjs = d.getElementsByTagName(s)[0], load = function(url, id) { if (d.getElementById(id)) {return;} js = d.createElement(s); js.src = url; js.id = id; fjs.parentNode.insertBefore(js, fjs); }; load('//connect.<a class="keyword" href="http://d.hatena.ne.jp/keyword/facebook">facebook</a>.net/en_US/<a class="keyword" href="http://d.hatena.ne.jp/keyword/sdk">sdk</a>.js#xfbml=1&amp;version=v2.0', '<a class="keyword" href="http://d.hatena.ne.jp/keyword/facebook">facebook</a>-jssdk'); load('<a href="https://apis.google.com/js/plusone.js',">https://apis.google.com/js/plusone.js',</a> 'gplus1js'); load('//platform.<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>.com/widgets.js', 'tweetjs'); }(document, 'script'));&lt;/script&gt; </pre> <p>これがこうなった。</p> <pre>&lt;script src="//connect.<a class="keyword" href="http://d.hatena.ne.jp/keyword/facebook">facebook</a>.net/en_US/<a class="keyword" href="http://d.hatena.ne.jp/keyword/sdk">sdk</a>.js#xfbml=1&amp;version=v2.0" id="<a class="keyword" href="http://d.hatena.ne.jp/keyword/facebook">facebook</a>-jssdk" async&gt;&lt;/script&gt; &lt;script src="<a href="https://apis.google.com/js/platform.js">https://apis.google.com/js/platform.js</a>" async defer&gt;&lt;/script&gt; &lt;script src="//platform.<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>.com/widgets.js" id="<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>-wjs" async&gt;&lt;/script&gt; &lt;script src="<a href="http://b.st-hatena.com/js/bookmark_button.js">http://b.st-hatena.com/js/bookmark_button.js</a>" async&gt;&lt;/script&gt; </pre> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA">はてな</a>を加えても4行。わーい。</p> <p>以前だったかLikeボタンを設定する時に、読み込む関数のなかでパラメータを設定してた記憶がある。そうだったらちょっと面倒だなと思っていたのだけれど、最近のソーシャルボタン系はURLのクエリーやら <code>data-</code> 属性で指定できるのね。なのでとくに必要なかった。</p> <p>もしある場合はどうしようかね。元のコードを見るしかないからどうも言えないか。</p> <hr /> <p>いまのところLikeボタンも<a class="keyword" href="http://d.hatena.ne.jp/keyword/Tweet">Tweet</a>ボタンもちゃんと動いているっぽい。他の非同期読み込み系だと<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Analytics">Google Analytics</a>があるけど、あれも読み込み部分は書き換えられそう。</p> myakura -webkit-alt プロパティ hatenablog://entry/12921228815733211186 2014-09-19T20:02:30+09:00 2014-09-19T21:11:29+09:00 PUAアイコンフォントのアクセシビリティ - Unreviewed これを読んでいて、内容とはまったく関係ないのだけれど -webkit-alt プロパティのことを思い出した。昨年11月に実装されたgenerated contentの読みを提供するためのプロパティだ。 Changeset 159591 – WebKit — AX: Implement CSS -webkit-alt property [webkit-dev] AX: Implement CSS -webkit-alt property (text alternative for generated content pseudo… <ul> <li><a href="http://takenspc.hatenablog.com/entry/2014/08/31/135631">PUAアイコンフォントのアクセシビリティ - Unreviewed</a></li> </ul> <p>これを読んでいて、内容とはまったく関係ないのだけれど <code>-webkit-alt</code> プロパティのことを思い出した。昨年11月に実装されたgenerated contentの読みを提供するためのプロパティだ。</p> <ul> <li><a href="http://trac.webkit.org/changeset/159591">Changeset 159591 – WebKit — AX: Implement CSS -webkit-alt property</a></li> <li><a href="https://lists.webkit.org/pipermail/webkit-dev/2013-September/025551.html">[webkit-dev] AX: Implement CSS -webkit-alt property (text alternative for generated content pseudo-elements ::before and ::after)</a></li> </ul> <p>実装された時期的に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a> 8/iOS8 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>に入っててもおかしくないのだけれど、どうなのかな。誰か確かめておくれ。</p> <p>装飾的なテキストをつける場合に、擬似要素にぶっこむという方法がある。</p> <pre>[data-new]::after { content: "\2730”; /* <a class="keyword" href="http://d.hatena.ne.jp/keyword/a.k.a.">a.k.a.</a> ✰ , literally “shadowed white star” */ } </pre> <p>これでOKとおもいきや、どうやらVoiceOverはgenerated contentも読み上げてしまって、この星印を“shadowed white star”と読んでしまうらしい。DOMに存在してたら<a class="keyword" href="http://d.hatena.ne.jp/keyword/ARIA">ARIA</a>の属性つけられるけれど、擬似要素なのでそうもいかない。そこで読みを提供するプロパティを導入したいと。</p> <pre>[data-new]::after { content: "\2730”; -<a class="keyword" href="http://d.hatena.ne.jp/keyword/webkit">webkit</a>-alt: "New"; } </pre> <p><code>attr()</code> も使えるので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%ED%A1%BC%A5%AB%A5%E9%A5%A4%A5%BA">ローカライズ</a>もしやすいとのこと。</p> <pre>[data-new]::after { content: "\2730”; -<a class="keyword" href="http://d.hatena.ne.jp/keyword/webkit">webkit</a>-alt: attr(data-new); } </pre> <p>ふうむ。擬似要素にテキストぶっこむというケースがどれくらいあるのかわかんないのだけど、広くサポートされる時代はすごく先になりそうだなあ。</p> <hr /> <p>これもまた全然関係ないのだけれど、絵文字を見る機会が増えてきた。ただ、グリフのデザインがよくないのか「これなんだろう?」と思ってしまう文字が多いのだよね。とくにぼくはケータイ持つのが遅くて絵文字の読解に慣れてないというのもあり、ハンディキャップというかなんかそういうのを感じている。絵文字イ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%C6%A5%E9%A5%B7%A1%BC">リテラシー</a>というのかね。</p> myakura meta-contactを使わずに連絡先をマークアップできないか hatenablog://entry/12921228815730045224 2014-08-12T01:18:14+09:00 2014-08-12T05:16:33+09:00 blink-devにこんなメッセージが。 Intent to implement: 'contact' meta extension Contact Meta Extensions たとえばおさいふ落とした時に銀行やカード会社に連絡とかしづらいから、電話番号、メールアドレス、住所を <meta name="contact"> なるものにぶっこんで、緊急な際にそのWebサイトに行く→ブラウザのメニューから「Call」ですぐ連絡できるよ!といったアイデアの実現をSamsungが考えているようで。そうですか…… なんでもこの電話、メール、住所のタプルは複数指定できるらしい。 <meta name="… <p>blink-devにこんなメッセージが。</p> <ul> <li><a href="https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/ZRX_5D4FmAI">Intent to implement: 'contact' meta extension</a></li> <li><a href="http://arpita.github.io/ContactMetaExtensions/">Contact Meta Extensions</a></li> </ul> <p>たとえばおさいふ落とした時に銀行やカード会社に連絡とかしづらいから、電話番号、メールアドレス、住所を <code>&lt;meta name="contact"&gt;</code> なるものにぶっこんで、緊急な際にそのWebサイトに行く→ブラウザのメニューから「Call」ですぐ連絡できるよ!といったア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>の実現を<a class="keyword" href="http://d.hatena.ne.jp/keyword/Samsung">Samsung</a>が考えているようで。そうですか……</p> <p>なんでもこの電話、メール、住所のタプルは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%A3%BF%F4">複数</a>指定できるらしい。</p> <pre><code>&lt;meta name="contact" content="Chicago: +1-555-555-5555 abc@xyz.com '5844 South Oak Street, Chicago, Illinois'; Brookfield: +1-444-444-4444 def@xyz.com '2341 Cherry Lane, Brookfield, Illinois'; Naperville: +1-333-333-3333 jkl@xyz.com '515 W. Jefferson, Naperville, Illinois 60540'"&gt;</code></pre> <p>おおう……</p> <p>先月には<a class="keyword" href="http://d.hatena.ne.jp/keyword/WHATWG">WHATWG</a>でだいたい同じような提案をしていたようで。</p> <ul> <li><a href="http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Jul/0098.html">Proposal to add website-* meta extensions</a></li> </ul> <p>この当時は <code>website-mail</code>, <code>website-number</code>, <code>website-address</code> と別のプロパティだったのにまとめられてしまった。どうしてそうなった。</p> <p>「<code>website-mail</code> は <code>&lt;link&gt;</code> に <code>mailto:</code> なURLにせいや」というコメントがあったんだけど「リンクタイプの拡張は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%C5%CD%CD%BD%F1">仕様書</a>き換えないといけないし…」という理由で <code>&lt;meta&gt;</code> らしい。<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#other-link-types">違うんだけどさ</a>。でもこういう標準化トラックの誤解はけっこうあるのだろうなあ。わかりやすさが必要ですね。</p> <h2>いまあるものでどうにかできないか</h2> <p>「電話番号」「メールアドレス」「住所」というプロパティを考えると、すでに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DC%A5%AD%A5%E3%A5%D6%A5%E9">ボキャブラ</a>リはある。<a class="keyword" href="http://d.hatena.ne.jp/keyword/vCard">vCard</a>とか<a class="keyword" href="http://d.hatena.ne.jp/keyword/Schema.org">Schema.org</a>とか。HTMLへの埋め込みについても、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Microformats">Microformats</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Microdata">Microdata</a>、RDFaとかがある。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Microformats">Microformats</a>はvisible metadata志向なのでとりあえず除外しよう。</p> <h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/Microdata">Microdata</a></h3> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Microdata">Microdata</a>+<a class="keyword" href="http://d.hatena.ne.jp/keyword/Schema.org">Schema.org</a>だとこうなる。</p> <pre><code>&lt;meta itemscope itemtype="http://schema.org/Organization" itemref="tel email adr"&gt; &lt;meta itemprop="telephone" content="+810000000000" id="tel"&gt; &lt;meta itemprop="email" content="foo@example.com" id="email"&gt; &lt;meta itemprop="location" content="123 Bar St. ..." id="adr"&gt;</code></pre> <p><code>&lt;meta&gt;</code> でやろうとすると入れ子にできないので <code>itemref</code> でプロパティそれぞれにつけた <code>id</code> を参照しないといけない。結果ちょっとつらくなる。あと <code>itemscope</code> のための <code>&lt;meta&gt;</code> もうれしくないね。 <code>location</code> のExpected Typeは <code>PostalAddress</code> か <code>Place</code> なので本当はもういっこ <code>itemscope</code> が増えてしまうのだけど、ちょっと楽をした。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Microdata">Microdata</a>もコンテンツがそれなりに構造化されて<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%AF%A5%A2%A5%C3%A5%D7">マークアップ</a>されていることをどこかで求めているので、フラットな <code>meta</code> だけだと無理がくる。入れ子にできたところで開発者は入れ子を嫌う(偏見)ので、受けが悪そうな気がする。</p> <h3>RDFa</h3> <p>RDFaだとこうかなあ。</p> <pre><code>&lt;meta typeof="schema:Organization" resource="#contact"&gt; &lt;meta property="schema:telephone" content="+810000000000" resource="#contact"&gt; &lt;meta property="schema:email" content="foo@example.com" resource="#contact"&gt; &lt;meta property="schema:location" content="123 Bar St. ..." resource="#contact"&gt;</code></pre> <p>すっきり書けるかなと思ったけどそんな変わらなかった。</p> <p>まずは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Schema.org">Schema.org</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CC%BE%C1%B0%B6%F5%B4%D6">名前空間</a>。RDFa 1.1だと<a href="http://www.w3.org/2011/rdfa-context/rdfa-1.1">schema接頭辞が組み込まれてる</a>ので <code>vocab</code> を省ける。ただ接頭辞が長いので名前がちょっと長たらしい。</p> <p><code>&lt;meta&gt;</code> が入れ子にできない問題は <code>resource</code> 属性でてきとうな<a class="keyword" href="http://d.hatena.ne.jp/keyword/URI">URI</a>をリソースに与えプロパティから参照させることで解決。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Microdata">Microdata</a>の <code>itemref</code> は <code>itemscope</code> からプロパティという一方向で、かつ <code>id</code> を再利用するのでプロパティそれぞれに別個の識別子をふらないといけないのがだるい。RDFaは <code>resource</code> なる新しい属性を導入したので、双方向にできている。</p> <p>あと、最初に <code>typeof</code> のためだけの <code>&lt;meta&gt;</code> を入れてるけど、この部分はプロパティのある要素に移動できるので、要素の数は3つに減らせたりする。</p> <pre><code>&lt;meta property="schema:telephone" content="+810000000000" typeof="schema:Organization" resource="#contact"&gt; &lt;meta property="schema:email" content="foo@example.com" resource="#contact"&gt; &lt;meta property="schema:location" content="123 Bar St. ..." resource="#contact"&gt;</code></pre> <p>3要素に全部 <code>typeof</code> 入れられもする。そうするとひとつの <code>&lt;meta&gt;</code> に依存しない利点がある。しないけど。</p> <p>データ的には嬉しくないだろうけど、<code>typeof</code> とっちゃうのもありかもしれない。</p> <pre><code>&lt;meta property="schema:telephone" content="+810000000000" resource="#contact"&gt; &lt;meta property="schema:email" content="foo@example.com" resource="#contact"&gt; &lt;meta property="schema:location" content="123 Bar St. ..." resource="#contact"&gt;</code></pre> <p>こうすると、<code>resource</code> がちょっと余計に見えるけど、まあお約束ということにすれば。</p> <hr /> <p>というわけで、各プロパティが分かれてる場合、RDFaだとただの <code>&lt;meta&gt;</code> とだいたい同じくらいの楽さで同じことができそうではある。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Schema.org">Schema.org</a>だとほんとは<a href="http://schema.org/ContactPoint"><code>ContactPoint</code></a>のほうが良さそうだけど、まあ。</p> <p><code>&lt;meta name="contact"&gt;</code> は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EF%A5%F3%A5%E9%A5%A4%A5%CA%A1%BC">ワンライナー</a>的なものだからできない。こういう時に<a class="keyword" href="http://d.hatena.ne.jp/keyword/RDF">RDF</a>/<a class="keyword" href="http://d.hatena.ne.jp/keyword/XML">XML</a>みたいな要素としても属性としても書けるっていうバーサタイルなものが欲しくなるけど、不幸しか呼ばないだろう。</p> <h2>フラットになると抜けるもの</h2> <p>ただまあ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Microdata">Microdata</a>やRDFaつかうとなると、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Microdata">Microdata</a>やRDFaの仕組みを実装しないといけない感がでてしまうので敬遠されるだろうなあという気はする。ただの <code>&lt;meta&gt;</code> にすれば、特定の名前に対して処理を決めうちしてやればいいので楽だ。<code>resource</code> とかも必要ないし。</p> <p>ただ「情報」として考えると無理がある。さっき「フラットな <code>&lt;meta&gt;</code>」と書いたけど、これはWebページというスコープが暗黙にあるからフラットになっている。連絡先はページにも関連するかもしれないけど、もとの提案は銀行の支店とかを考えているようなのでページとは直接関係しない情報だ。ページに直接関わらないものを <code>&lt;meta name="foo"&gt;</code> に押し込むような名前と処理を定義してもいいんだろうけど、だいぶ乱暴ではないか。</p> <p>拡張ごとにマイクロ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%F3%A5%BF%A5%C3%A5%AF%A5%B9">シンタックス</a>を増やすのは、健康的ではないよね。そういう点でOGPはだいぶ頑張ったしえらいなという気はする。</p> <p>もうちょっと自由度が低くて、でも書くぶんにはふつうの <code>&lt;meta&gt;</code> と変わらないRDFaのサブセットがあればいいのかもしれない。<code>resource</code> さえ許容できれば、さっき書いたのでだいぶいい線いってるとは思うけど。</p> myakura ServiceWorkerの記事を書いた&所感 hatenablog://entry/12921228815729309307 2014-07-31T23:29:48+09:00 2014-07-31T23:29:48+09:00 HTML5 Experts.jpにServiceWorkerの記事を書いた。 Google I/O 2014──ServiceWorkerでネイティブアプリとの差を縮めよう Google I/Oで見たServiceWorkerのセッションを紹介したもの。セッションの内容を文字にして説明しているという雑な記事。セッションのビデオを見るよりは早いかと思うので、見てない人にはよいかと。見ている人は…なんだろ、紹介されたコードにちょっとコメント入れたので、それを…… コードで思い出した。サンプルで&が&amp;になってしまってるんだけど、なんかWordPressのプラグインのせいなのかどうしても直せな… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/HTML5">HTML5</a> Experts.jpにServiceWorkerの記事を書いた。</p> <ul> <li><a href="http://html5experts.jp/myakura/8365/">Google I/O 2014──ServiceWorkerでネイティブアプリとの差を縮めよう</a></li> </ul> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20I/O">Google I/O</a>で見たServiceWorkerのセッションを紹介したもの。セッションの内容を文字にして説明しているという雑な記事。セッションのビデオを見るよりは早いかと思うので、見てない人にはよいかと。見ている人は…なんだろ、紹介されたコードにちょっとコメント入れたので、それを……</p> <p>コードで思い出した。サンプルで<code>&amp;</code>が<code>&amp;amp;</code>になってしまってるんだけど、なんか<a class="keyword" href="http://d.hatena.ne.jp/keyword/WordPress">WordPress</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3">プラグイン</a>のせいなのかどうしても直せなかった。Syntax Highlighting的な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3">プラグイン</a>もよくわからず使えず…WP力が低い。</p> <p>記事を書いていていろいろ考えたことがあったので以下雑多に後記てきなものをば。</p> <h2>ServiceWorkerの更新</h2> <p>記事でも書いたけども、そんな触れられてなかったSWの更新についてちょっとだけ広げる。</p> <p>AppCacheの「セットされたら最後」問題をアドレスするため、ServiceWorkerではブラウザが最低でも24時間に一度はSWの更新チェックをすることになっている。FetchしてみてSWが更新されていれば、そのSWの<code>oninstall</code>ハンドラを実行する。だいたいキャッシュの追加とかになると思う。</p> <p><code>oninstall</code>ハンドラが処理されたあとは待機状態になる。待機する理由は前のバージョンのSWが実行されているタブがあったりすると問題だから。前のバージョンがコントロールしているアプリがすべて終了したら新しいSWが起動して、<code>activate</code>イベントが発火する。なのでSWに<code>onactivate</code>ハンドラを書いとけばそれが処理される。<code>activate</code>は<code>fetch</code>が発火する前に必ず発火するようになってるので、破壊的?な処理はここですることになると。</p> <p>待機せずに新しいSWをすぐ使わせたい場合は、<code>oninstall</code>ハンドラ内で<code>e.replace()</code>を実行すると入れ替わってくれる。キャッシュに追加し忘れたものを追加したとか、そういう小さい&致命的なfailureが起こらない場合はこれを使ってもいいのかなと。</p> <p>ちょっと気になってるのが、v2が待機状態になる前に<code>oninstall</code>が走ること。ちゃんと仕様読んでないだけなんだけど、以下の場合どうなるのかなと。</p> <ol> <li>v1インストールで <a href="https://example.com/foo.png">https://example.com/foo.png</a> をキャッシュ</li> <li>v2開発。foo.<a class="keyword" href="http://d.hatena.ne.jp/keyword/png">png</a> がちょう変わる</li> <li>v2インストールでその新しい foo.<a class="keyword" href="http://d.hatena.ne.jp/keyword/png">png</a> をキャッシュ</li> <li>開きっぱのタブがあってv2が待機状態に</li> <li>foo.<a class="keyword" href="http://d.hatena.ne.jp/keyword/png">png</a>へのfetchが行われる</li> </ol> <p>こうなったとき、v2のキャッシュ参照されたりしないのかなと。ちゃんと仕様読もうか……</p> <h2>named Cache</h2> <p>セッションや紹介記事とかで、最初のinstall時にキャッシュに“static-v1”という名前をつけて静的リソースをキャッシュさせている。</p> <pre><code>this.oninstall = function (e) { e.waitUntil( caches.create('static-v1').then(function (cache) { return cache.add( '/', // ... ) }) ) }</code></pre> <p>Cacheオブジェクトは自動では消えないのでかなり面白いんだけど、この「自動で消えないものに名前を付けられる」というところで、特定の特定のnamed cache前提のコードを書いてしまうケースがあるのではないかとちょっと思った。</p> <pre><code>// v1 this.oninstall = function (e) { e.waitUntil( caches.create('static-images').then(function (cache) { return cache.add( '/img/...', '/img/icons/...', // ...</code></pre> <p>v1時にこういう画像のキャッシュを用意したとする。その後バージョンを上げるんだけど、使ってる画像は一緒ということで、常に「static-images」なCacheを参照するようにしちゃう。</p> <pre><code>// v2 this.onfetch = function (e) { if (e.request.context === 'image') { e.respondWith( caches.get('static-images').then(function(responses) { return responses[0] } ).catch(function () { return e.default() }) } }</code></pre> <p>で、「画像変えてないのにインストール時にFetch走るとかやだよね、消そっか」みたいなノリで<code>oninstall</code>内の <code>caches.create('static-images')</code> なところを消してしまった。これで何が起こるかというと、v2以降に始めてアクセスした人には「static-images」なキャッシュが作られないので、悲しくなると。</p> <p>単なる思考実験ではあるんだけど、</p> <ul> <li>Webという「インストール」の概念がなかったものにそれがもたらされる</li> <li>自動では消えないキャッシュを用意でき、さらに参照しやすい名前までつけられる</li> </ul> <p>というのがあるので、最初から継続的に開発しているひとだと変にこういう状態に陥ったりしないかなと。</p> <p>開発<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB">ツール</a>側にもSWにくっついたCacheを削除するとかそういうオプションは要るだろうなあ。</p> <h2>Fetchのrequest context</h2> <p>SWのセッションを見てておもしろかったのが、テンプレート適用やら画像のトランスコードやら、オフラインに限らないプロキシ的な使い方をするところ。</p> <p>画像のトランスコードなんかは、フォーマットに対応してないブラウザでの表示だけじゃなく、対応してるブラウザで画像をダウンロードさせたときにも使えるかなと思った。ほら、WebPファイルダウンロードできても困るケースはけっこうあると思うので。</p> <p>Fetch仕様ではrequest contextに<code>download</code>なんてものがある。<code>&lt;a download href='blah'&gt;</code>なリソースのfetchはそんなコンテキストらしい。これがSWでも取得できたら画像を<a class="keyword" href="http://d.hatena.ne.jp/keyword/URI">URI</a>化したものを<code>href</code>にぶっこんどいて、<code>onfetch</code>内でひっかけられたらなと。</p> <pre><code>&lt;a href="foo.webp" download&gt;donwload image&lt;/a&gt; </code></pre> <pre><code>this.onfetch = function (e) { if (e.request.context === 'donwload') { e.respondWith( e.default().then(function (r) { if (r.headers.get('content-type') === 'image/webp') { return transcode(r.body); } else { return r; } }) ) } })</code></pre> <p>こんなことができるとなあと思ってたんだけど、<a href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#fetch-event-interface"><code>FetchEvent.context</code>には<code>download</code>がなかった</a>…うおお。</p> myakura 表現のコンポーネントとエレメント指向 hatenablog://entry/12921228815727193442 2014-06-30T23:59:00+09:00 2014-10-14T06:24:06+09:00 このところいろいろ思っていたWeb Componentsでなにを要素とするのかという疑問。Polymerに表現を要素化しているものがあったので、すこし考えてみた。 <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20I/O">Google I/O</a>に行ってきたのでそれ関連の話題を。</p> <h2>Paper Elementsのエフェクト要素</h2> <p><a href="http://www.google.com/design/spec/">Material Design</a>という<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%B6%A5%A4%A5%F3%B8%C0%B8%EC">デザイン言語</a>が出て、そのWebへの適用手段として<a href="http://www.polymer-project.org/">Polymer</a>の<a href="http://www.polymer-project.org/docs/elements/paper-elements.html">Paper elements</a>が発表された。</p> <p><a href="http://io2014codelabs.appspot.com/">CodeLabs</a>でもPolymerとPaper ElementsでTodoリストアプリをPolymerとPaper Elementsで作るというコースがあった。この中に、<a href="http://io2014codelabs.appspot.com/static/codelabs/polymer-build-mobile/#8">エフェクトを指定するステップ</a>がある。ここでほーと思ったのが、影をキャストする際には<code><a href="http://www.polymer-project.org/docs/elements/paper-elements.html#paper-shadow">paper-shadow</a></code>を、波紋の効果を出す<a href="http://www.polymer-project.org/docs/elements/paper-elements.html#paper-ripple"><code>paper-ripple</code></a>を使うこと。エフェクトが要素になっているのだ。</p> <p>表現が必ず要素化されているわけでもない。固定化された<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%D0%A1%BC">ツールバー</a>があって、スクロールし始めた際に下のコンテンツから浮き出るような表現をMaterial Designではwaterfallと呼んでるのだけど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%D0%A1%BC">ツールバー</a>にその表現を与えるには<code>mode="waterfall"</code>という属性をつけてやるらしい。</p> <h2>エフェクトの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>化</h2> <p>影や波紋がひとつの要素として定義されているのはどのUIでも汎用的に使われる視覚効果で、それを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>として使いたいからなのだろう。<a href="http://www.polymer-project.org/docs/elements/material.html#material-effects">ドキュメンテーション</a>からは、自分たちが定義する<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>にエフェクトを与えたい時にこれらの要素を使えと書かれている。waterfallが要素化されていないのは、いち資格効果というよりも、スクローラブルなUIのいち表現という面が強いからだろう。</p> <p>なので、エフェクトも必ず要素にせよというわけではない。そう言われたとしても、それはPolymerのお作法という側面が強いはず。たぶん…</p> <p>とはいえ、Polymerであれなんであれ、再利用可能な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>はインポートしちゃえばいろいろできるので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>時代が来たらコスメティックな表現だけの「ユーティリティ」要素が増える可能性だってある。そうなるとページ内の各要素に<code>paper-shadow</code>を与えて〜と、非効率な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%AF%A5%A2%A5%C3%A5%D7">マークアップ</a>が増えるかもしれない。</p> <h2>エレメンタル、クラシカル</h2> <p>古い人間なので、表現まわりは<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>をはじめとする、表現の定義を要素に適用するアプローチのほうがいいんじゃないかと思ってしまう。大体の場合において、そちらのほうが高効率な気がするからだ。ところがWeb Componentsでは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>内で使われる視覚表現であったり挙動であったりを分離して管理・適用する仕組みが弱い気がする。Decoratorsがひとつの解なのだろうけど、いまのところ用意されてない。</p> <p>Decoratorsのプライオリティが低い理由として、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>を読み込む際にはself-containedなもののほうがパフォーマンスや依存関係の面で都合が良いということがあるのかなと思う。</p> <p>もうひとつは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EF%A1%BC%A5%AF%A5%A2%A5%E9%A5%A6%A5%F3%A5%C9">ワークアラウンド</a>でなんとかできるというのもあるんだろう。現在のPolymerもそうしている。たとえばさっきの<code>paper-shadow</code>も、タグを子として書くだけという方法のみを提供してるわけではない。</p> <blockquote cite="http://www.polymer-project.org/docs/elements/paper-elements.html#paper-shadow"> <p>The <code>paper-shadow</code> element is a helper to add shadows to elements. Paper shadows are composed of two shadows on top of each other. We mimic this effect by using two elements on top of each other, each with a different drop shadow. You can apply the shadow to an element by assigning it as the target. If you do not specify a target, the shadow is applied to the <code>paper-shadow</code> element's parent element or shadow host element if its parent is a shadow root. Alternatively, you can use the <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a> classes included by this element directly.</p> </blockquote> <p>併記してDOMで関連づけることもできれば、各ステートをclass属性値としてexposeしている。なので今のUI<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>がやってるやり方も使える。HTMLもしくは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>で適用することになるから、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>でどうこうという話ではないんだけれど、直接書くよりはいくぶんか効率よいのではないか。</p> <p>でも<code>paper-ripple</code>には<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%AD%A5%E5%A5%E1%A5%F3%A5%C6%A1%BC%A5%B7%A5%E7%A5%F3">ドキュメンテーション</a>を見る限りはそういうのがないんだよね。なんでだろ。</p> <h2>DeclarativeとImperative</h2> <p>Web Componentsを語るときにたまに出る単語として“Declarative”, “Imperative”というものがある。HTMLのタグはdeclarativeで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>でDOM操作をするのはimperativeだ。<a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>はdeclarativeで<a class="keyword" href="http://d.hatena.ne.jp/keyword/Canvas">Canvas</a>はimperative、AppCacheはdeclarativeでService Workersはimperativeだ。そんな対立というよりは対比がある。</p> <p>PolymerはDeclarativeな性質をかなり推している。というよりもエレメンタル指向なのかもしれない。だからといってImperativeなものが否定されるわけではない。ただ、declarativeはそのわかりやすさから“magic”を生みだし、時たま不都合や混乱を生み出す。古いもので&lt;select&gt;、まあまあ新しいものでAppCacheとか。</p> <p>わかりやすさの責任がとれないと、僕らが不幸になる。Magicではなく、どう振る舞うのかが説明されて、はじめて強力なものになる。Extensive Web Manifestoが目剤しているのはそこだ。Polymerが要素でなんでもしようとしてるけど、それはWeb Componentsが下にあって、モデルを提供しているからになる。こうすると、エレメンタルだけではなくクラシカルなアプローチも提供できる。影を要素として日の下に出すことも、今までのようにクラスに潜ませることもできる。</p> <hr /> <p>DeclarativeとImperative、エレメンタルとクラシカル、相互に補完することで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>のデザインはより柔軟になるんだろう。ただ設計をするひとは、どこでimperative(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>をごりごり書くか)それともdeclarative(タグ書きまくるか)にするのかということをそれないり意識しないといけないのかも。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>ならいいけれど、文書の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%AF%A5%A2%A5%C3%A5%D7">マークアップ</a>として要素を作るときはさらによく分からんくなるのかも。要素なのかそれともクラスなのか。</p> <p>実際に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>書く前に、そんなことばっかり気になってしまっている。</p> myakura Safari 8?の機能予想 hatenablog://entry/12921228815725303678 2014-05-31T22:56:08+09:00 2014-06-01T14:22:25+09:00 WWDC直前ということでSafariの話題を。 といってもネタは3週間以上も前のもの。5月8日に「safari-538.34-branch」というWebKitのブランチが切られた。 Changeset 168485 – WebKit — New Branch 昨年も書いたのだけど、これまでの動きから考えてこれが次のSafariのもとになるブランチのはず。というわけでコミットログとかから次のSafariを予想しようかと。 WebKitのMac portで有効にされる機能は、FeatureDefines.xcconfig というファイルで管理されている。これらはビルドフラグなので、有効にされてない… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/WWDC">WWDC</a>直前ということで<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>の話題を。</p> <p>といってもネタは3週間以上も前のもの。5月8日に「<a class="keyword" href="http://d.hatena.ne.jp/keyword/safari">safari</a>-538.34-branch」という<a class="keyword" href="http://d.hatena.ne.jp/keyword/WebKit">WebKit</a>のブランチが切られた。</p> <ul> <li><a href="http://trac.webkit.org/changeset/168485">Changeset 168485 – WebKit — New Branch</a></li> </ul> <p><a href="http://myakura.hatenablog.com/entry/2013/06/04/210702">昨年も書いた</a>のだけど、これまでの動きから考えてこれが次の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>のもとになるブランチのはず。というわけでコミットログとかから次の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>を予想しようかと。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/WebKit">WebKit</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Mac">Mac</a> portで有効にされる機能は、<a href="https://github.com/WebKit/webkit/blob/master/Source/WebCore/Configurations/FeatureDefines.xcconfig">FeatureDefines.xcconfig</a> というファイルで管理されている。これらはビルドフラグなので、有効にされてないと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CA%A5%A4%A5%C8%A5%EA%A1%BC">ナイトリー</a>でも使えない。あと、ランタイムフラグもあるらしいんだけどこれは詳しく知らない。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a> 8に入りそうなもの</h2> <p><a href="http://trac.webkit.org/browser/branches/safari-538.34-branch/Source/WebCore/Configurations/FeatureDefines.xcconfig">538ブランチのFeatureDefines.xcconfig</a>で有効にされてるものはこんな感じ。</p> <ul> <li><a href="http://trac.webkit.org/changeset/151247">CSS Shapes</a></li> <li><a href="http://trac.webkit.org/changeset/166993">Media Source Extensions</a></li> <li><a href="http://trac.webkit.org/changeset/161241">Promises</a></li> <li><a href="http://trac.webkit.org/changeset/161882">Subpixel Layout</a></li> <li><a href="http://trac.webkit.org/changeset/159550"><code>&lt;template&gt;</code> Element</a></li> <li><a href="http://trac.webkit.org/changeset/167958">FTL JIT</a></li> <li><s><a href="http://trac.webkit.org/changeset/156447">Indexed Database API</a></s></li> </ul> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/FTL">FTL</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/JIT">JIT</a>は昨年ブランチ後にパッチがガンガン入っていたし、先日<a href="https://www.webkit.org/blog/3362/introducing-the-webkit-ftl-jit/">Surfin' Safariでも大々的に取り上げられた</a>。</p> <p>このうち、IndexedDBについては<a href="https://bugs.webkit.org/show_bug.cgi?id=121918#c0">バグのコメント</a>を読むと<code>window.IndexedDB</code>にアクセスしても<code>null</code>を返すように仕組んであるとか書いてある。<a href="http://trac.webkit.org/browser/trunk/Source/WebCore/Modules/indexeddb/IDBFactory.h#L53">ソースのコメント</a>によるとまだ作ってる最中という話だけど、状況はどうなのかしら。</p> <h2>その他入ったもの</h2> <ul> <li><a href="http://trac.webkit.org/changeset/154992"><code>responseType='json'</code> in XHR</a></li> <li><a href="http://trac.webkit.org/changeset/166246"><code>ImageData()</code></a></li> <li><a href="http://trac.webkit.org/changeset/161876"><code>Text()</code></a></li> </ul> <p>とかとか。昨年から真面目に追いかけてないのもあって思い出せない……</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScriptCore">JavaScriptCore</a>に追加されたもの</h2> <p>JSCにはENABLEマクロ的なものが見当たらない。ここらへん<a class="keyword" href="http://d.hatena.ne.jp/keyword/SpiderMonkey">SpiderMonkey</a>みたくそんな<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B8%E5%CA%FD%B8%DF%B4%B9">後方互換</a>性重視してないのかなという感じがする。</p> <p>というわけで<a href="http://trac.webkit.org/log/trunk/Source/JavaScriptCore">JavaScriptCoreのログ</a>をふにふにと追ってみた。</p> <ul> <li><a href="http://trac.webkit.org/changeset/167797"><code>Array.prototype.find()</code></a></li> <li><a href="http://trac.webkit.org/changeset/167380"><code>Array.prototype.fill()</code></a></li> <li><a href="http://trac.webkit.org/changeset/165795"><code>Math.hypot()</code></a></li> <li><a href="http://trac.webkit.org/changeset/165047"><code>Number.prototype.clz()</code></a></li> <li><a href="http://trac.webkit.org/changeset/156791"><code>Array.prototype.keys()</code>/<code>values()</code>/<code>entries()</code></a></li> <li><a href="http://trac.webkit.org/changeset/158401"><code>Math</code> functions</a></li> <li><a href="http://trac.webkit.org/changeset/159008"><code>Map</code></a> iterators</li> <li><a href="http://trac.webkit.org/changeset/159031"><code>Set</code></a> iterators</li> <li><a href="http://trac.webkit.org/changeset/156910">for-of</a></li> <li><a href="http://trac.webkit.org/changeset/156785">Destructuring assignment</a></li> <li><a href="http://trac.webkit.org/changeset/154916"><code>Set</code></a></li> <li><a href="http://trac.webkit.org/changeset/154861"><code>Map</code></a></li> <li><a href="http://trac.webkit.org/changeset/157545">Spread operators</a></li> </ul> <p>ES6がいろいろ入った。Spread oprsやDestructuring assgnmnt、for-ofはうれしい。</p> <p>あと<a href="http://trac.webkit.org/changeset/164139"><code>Array</code>の関数がJavaScriptで書き直された</a>りもしていた。その前に<a href="http://trac.webkit.org/changeset/163960">ビルトイン関数をJavaScriptで書けるようになった</a>ので、今後他のものも<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>で書かれるようになるんだろうか。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a> 8に入りそうにないもの</h2> <p>538.34ブランチで無効にされてるものはこちら。</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a> Exclusions</li> <li>Shared Workers</li> <li>Grid Layout</li> <li><a href="http://trac.webkit.org/changeset/165651">Canvas Path</a></li> <li><a href="http://trac.webkit.org/changeset/166595">Web Timing</a></li> <li><a href="http://trac.webkit.org/changeset/153541"><code>&lt;input type="color"&gt;</code></a></li> </ul> <p>しゅーん。</p> <p>Web TimingはNavigation Timing, Resource Timing, User Timingを指す(もともと<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>から提案された時にWeb Timingという1つの仕様だったことに由来する)。Trunkで有効にされてうおーって思ったのだけど、ブランチが切られてからしばらくして消されてしまった。ただ<a href="http://trac.webkit.org/changeset/168647">作業はしている</a>ので、実装が追いついてないのかもしれない。</p> <p>機能的にこれからというものもある。<a href="http://trac.webkit.org/changeset/166618">CSS Exclusionsはparsingしか入ってなかったらしい</a>。</p> <p>他にも<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromium">Chromium</a>が離脱した絡みか、Shadow DOMやらiframe@seamlessとかいろいろなくなっていたりする。</p> <h2>よくわからないもの</h2> <p>条件付きで有効にされているものがある。そのひとつがtelephone number detectionで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>の電話番号に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BC%AB%C6%B0%A5%EA%A5%F3%A5%AF">自動リンク</a>つけるやつ。たぶん<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>のコードをupstreamした関係で<a class="keyword" href="http://d.hatena.ne.jp/keyword/WebKit">WebKit</a>の方にも入ったのだけど、今年のはじめの方にちょこちょこ作業されてて、<a href="http://trac.webkit.org/browser/branches/safari-538.34-branch/Source/WebCore/Configurations/FeatureDefines.xcconfig#L193">Mac port用のマクロが用意</a>されている。有効にされてるのは <code>ENABLE_TELEPHONE_NUMBER_DETECTION_macosx_101000</code> となってるので、10.10なんだろう。あれが便利だと思ったことはないのだけれど、デスクトップにもあの機能がつくのかな。</p> <p><code>ENABLE_<var>FOO</var>_macosx_10<var>nnnn</var></code> っていう特定の<a class="keyword" href="http://d.hatena.ne.jp/keyword/OS%20X">OS X</a>で有効にされてるのは他にもある。</p> <hr /> <p>こんな感じかなあ。さてどうなりますかね。</p> myakura 新しいiPhoneの解像度とCSSピクセル幅を考える hatenablog://entry/12921228815722999067 2014-04-30T21:09:46+09:00 2014-04-30T21:09:46+09:00 そろそろSafari 8?のベースになるWebKitのブランチが切られるかなと思って待っていたら月末になってしまった。ネタがないのでiPhoneの噂話でもしよう。 新iPhoneの画面解像度は? まず、確かな情報筋()によると、4.7インチと5.5インチのモデルが出ると。 4.7インチは750×1334らしい。現行iPhoneのディスプレイと同じ326ppiなものを4.7インチにするとこうなると。5.5インチだとフルHDな1080×1920らしい。こちらは新しいディスプレイで401ppiだって。 さて、5.5インチについてはまだわかるんだけど、4.7インチの謎解像度はないのではないかと思ってい… <p>そろそろ<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a> 8?のベースになる<a class="keyword" href="http://d.hatena.ne.jp/keyword/WebKit">WebKit</a>のブランチが切られるかなと思って待っていたら月末になってしまった。ネタがないので<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>の噂話でもしよう。</p> <h2>新<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>の画面解像度は?</h2> <p>まず、<a href="http://www.macrumors.com/roundup/iphone-6/">確かな情報筋()</a>によると、4.7インチと5.5インチのモデルが出ると。</p> <p>4.7インチは750×1334らしい。現行<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>のディスプレイと同じ326ppiなものを4.7インチにするとこうなると。5.5インチだと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EBHD">フルHD</a>な1080×1920らしい。こちらは新しいディスプレイで401ppiだって。</p> <p>さて、5.5インチについてはまだわかるんだけど、4.7インチの謎解像度はないのではないかと思っている。というのはデバイス非依存ピクセルを想像すると2つのモデルで幅が異なる可能性が高いから。同じディスプレイが使えるという製造観点での利点や理由はあれど、アプリとかの観点から考えると煩わしすぎるわけですよ。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>ピクセルで見る<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>の横幅</h2> <p>デバイス非依存ピクセル…面倒なので<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>ピクセルにしとこう(<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>に限った話じゃないけど)。あ、あとviewportは<code>width=device-width</code>のときね。よし。</p> <p>ピクセル密度や画面解像度の変更はあれど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>は登場時から横幅320csspxを維持してきた。<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone%203G">iPhone 3G</a>までは320×480。<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone%204">iPhone 4</a>では<a class="keyword" href="http://d.hatena.ne.jp/keyword/Retina">Retina</a> displayとして640×960としたものの、レイアウト面でアプリやWebコンテンツへの影響がないように、1csspxを2dpxで描画するようにした。<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>ピクセル的には、320×480と変わらない。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone%205">iPhone 5</a>では640×1136になった。これまで3:2だった<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B9%A5%DA%A5%AF%A5%C8%C8%E6">アスペクト比</a>が変わって16:9(くらい)になった。HDなコンテンツをレターボックスなしで見られるようにするためだろうけど、幅320という<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>ピクセルは変えずに高さを増やした。結果として320×568と収まりが悪い感じになった。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>はだいたい幅360</h2> <p>最近の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A1%BC%A5%C8%A5%D5%A5%A9%A5%F3">スマートフォン</a>の多くは、◯◯HDみたいな解像度が多い。HDを冠するだけあってHDコンテンツとの相性がよいんだろう。最初はたぶんqHDで540×960。次にHDで720×1280。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EBHD">フルHD</a>のも出てきて1080×1920。2Kなんてのも発表されて1440×2560。もうよくわかんなくなるよね。</p> <p>解像度はばらけているけど、ピクセル密度がそれぞれ違うので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>ピクセル的にはこれらすべてが360×640になる。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>でも一貫しているところはあったんだよ!!</p> <p>さて、横幅が360csspxというの、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>に比べて40csspxも余裕がある。つくりによるけど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>では詰まったWebサイトも<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>では横にちょっと余裕がある。◯<a class="keyword" href="http://d.hatena.ne.jp/keyword/VGA">VGA</a>な端末だと横幅320csspxだけど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>と同じなのでそんな影響はない。</p> <p>Nexus 4はなぜだか768×1280→幅384csspxという謎仕様だったけれど忘れとこう。見た目も<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B9%A5%DA%A5%AF%A5%C8%C8%E6">アスペクト比</a>もよいと思うけど、たぶん悲しみしか生んでない。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a> 6は幅360になるのか</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a> 6のうわさスペックを見ると、4.7インチモデルは幅750、5.5インチモデルは幅1080。ピクセル密度から考えると、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>ピクセルは4.7インチモデルでは幅375、5.5インチモデルでは幅360となる。</p> <p>まず、320というこれまでの幅がでてこない。360以上になっている。これまで頑なに320を維持していたのに、それがついに変わるのか。</p> <p>Webコンテンツに関しては、ゲームとかだとけっこう辛いのかな。ただ静的なWebサイトなら最近の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>を考えているならそんな問題ない気がする。考えてなくてもたぶんそんな問題は出ないんじゃあないか。</p> <p>影響があるのはやっぱりアプリだろう。これまでみたくレターボックスが導入されると、edge-to-edgeなデザインが生きない。拡大モードを使うと、360÷320=1.125なので、うっすらぼける。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Retina">Retina</a> displayほどではないだろうけど、ちょっと影響が出てくる。</p> <p>ただ、iOS7での大きなテイスト変更もあるので、アプリはいずれアップデートしないといけない。また、その新しいテイストだと画像とかよりテキストを推している感じがするので、拡大によるぼけはけっこう避けられるのかもしれない。なので幅360へのスイッチは、それなりにタイミングがいいのかもしれない。</p> <h2>ほんとに4.7インチ?</h2> <p>すっかり360前提で話をしてしまった。でもやっぱり、4.7インチモデルとやらから導かれる幅375csspxというのは考え難い。異なるモデルで幅が違うとかね。というわけで、もし幅を変えるのであれば2モデルとも幅360csspxにそろえるのではないか。</p> <p>4.7インチという話はリークされたケースから来ているらしい。それくらいの大きさで◯HDなものだと解像度はHD、720×1280が適当かなあ。これで<a class="keyword" href="http://d.hatena.ne.jp/keyword/PPI">PPI</a>を計算すると312くらい、これまでの326ではない。</p> <p>逆にこれまでの326を使って幅720とした場合、大きさが4.5インチ程度になる。言われている4.7インチより0.2インチ小さい。5mmくらい、さすがに誤差とはいえないか……</p> <p>ピクセル密度比が下がることは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Retina">Retina</a> display的にどうなのだろうか。では3xの新しいディスプレイになったとする。想定される解像度は1920×1080。これで4.7インチな端末は…HTC Oneがそうらしい。ふーむ。</p> <h2>まとめ(られてない)</h2> <p>噂されてる解像度がほんとなら、これまで維持してきた幅320csspxがついに終わる。狭くなるわけじゃないのでレイアウト崩れは想像しづらいけど、アプリ、とくにゲームとかは大変そう。</p> <p>ただ4.7インチモデルの噂においては解像度の予測が疑わしい。幅360ベースになおすと326ppiのディスプレイは使えない。4.7インチモデルではピクセル密度比3、5.5インチモデルでは4になったりするかもしれない。</p> <p>まあ、わかんないってことで。幅は360になるんじゃないかとは思うけど。</p> myakura Sassでlinear-gradient()のmixinをつくる その6 hatenablog://entry/12921228815719718852 2014-03-10T18:59:24+09:00 2014-03-10T18:59:24+09:00 このエントリはCSS Preprocessor Advent Calendar 2012の記事の続編です。 察せ。 Sass 3.3がついにリリースされました。リリースされないものだと思っていましたがよかったです。アルファ版からインストールしていましたが、いまいち使っていませんでした。というわけで、これまで作ったMixinからSass 3.3の新機能を実際に使えないか試してみます。 Part 8: マップライクな処理はマップに置換え linear-gradient()と-webkit-linear-gradient()など接頭辞つきのバージョンとでは方向を示すキーワードが違います。対応関係があ… <p>このエントリは<a href="http://myakura.hatenablog.com/entry/2012/12/13/220000">CSS Preprocessor Advent Calendar 2012の記事</a>の続編です。</p> <p>察せ。</p> <hr /> <p><a href="http://blog.sass-lang.com/posts/184094-sass-33-is-released">Sass 3.3がついにリリース</a>されました。リリースされないものだと思っていましたがよかったです。<br />アルファ版からインストールしていましたが、いまいち使っていませんでした。というわけで、これまで作ったMixinからSass 3.3の新機能を実際に使えないか試してみます。</p> <h2>Part 8: マップライクな処理はマップに置換え</h2> <p><code>linear-gradient()</code>と<code>-webkit-linear-gradient()</code>など接頭辞つきのバージョンとでは方向を示すキーワードが違います。対応関係があるためマップやハッシュで表現したいところですが、これまでのSassにはそういったものがなく、<a>Sass 3.2の次に実装する</a>とされていました。<br />そしてSass 3.3でついに<a href="http://sass-lang.com/documentation/file.SASS_CHANGELOG.html#sassscript_maps">マップが実装</a>されました。わーい。</p> <p>Sassのマップは<code>(<var>key1</var>: <var>value1</var>, <var>key2</var>: <var>value2</var>)</code>のように、ラベルつきのカンマ区切りリストみたいなかたちになってます。マップから値を取り出したりマップに値を追加したりする際には、新たに定義された<a href="http://sass-lang.com/documentation/Sass/Script/Functions.html#map-functions">マップの関数</a>を使います。</p> <p>というわけで、キーワードの変換部分に使っていたマップライクな処理をマップに置換えてみます。<br />まずはキーワード版の処理を。こうなってました。</p> <pre>@mixin lg-keyword($keyword, $colorstops...) { $prefixes: '-<a class="keyword" href="http://d.hatena.ne.jp/keyword/webkit">webkit</a>-'; // 標準のキーワード $standard_keywords: to bottom, to left, to top, to right, to top left, to top right, to bottom right, to bottom left, to left top, to right top, to right bottom, to left bottom; // 接頭辞版のキーワード $legacy_keywords: top, right, bottom, left, bottom right, bottom left, top left, top right, right bottom, left bottom, left top, right top; // キーワードのインデックスを取得 $idx: index( $standard_keywords, $keyword ); // キーワードが不正な場合は何も出さない @if $idx { // マッチする接頭辞版のキーワードを取得 $legacy_keyword: nth( $legacy_keywords, $idx ); @each $prefix in $prefixes { background-image: #{$prefix}linear-gradient( $legacy_keyword, $colorstops); } background-image: linear-gradient($keyword, $colorstops); } }</pre> <p>標準のキーワード、接頭辞版のキーワードを2つのリストにして、引数に与えられたキーワード(標準版)のインデックスを取得。出力時にそのインデックスを使い、接頭辞版のキーワードを引っ張ってきています。<br />これがマップを使うとこうなります。</p> <pre>@mixin lg-keyword($keyword, $colorstops...) { $prefixes: '-<a class="keyword" href="http://d.hatena.ne.jp/keyword/webkit">webkit</a>-'; $keywords_map: ( to bottom: top, to left: right, to top: bottom, to right: left, to top left: bottom right, to top right: bottom left, to bottom right: top left, to bottom left: top right, to left top: right bottom, to right top: left bottom, to right bottom: left top, to left bottom: right top ); // キーワードが不正な場合は何も出さない @if map-has-key($keywords_map, $keyword) { @each $prefix in $prefixes { background-image: #{$prefix}linear-gradient(map-get($keywords_map, $keyword), $colorstops); } background-image: linear-gradient($keyword, $colorstops); } }</pre> <p><code>(<var>標準版</var>: <var>接頭辞版</var>, ...)</code>というマップに作り直しました。引数が標準版のキーワードになっているかを調べるには<a href="http://sass-lang.com/documentation/Sass/Script/Functions.html#map_has_key-instance_method"><code>map-has-key()</code>関数</a>を使えばOK。マップから値を取り出すときは<a href="http://sass-lang.com/documentation/Sass/Script/Functions.html#map_get-instance_method"><code>map-get()</code>関数</a>を使います。</p> <p>ソースを整形してるため行数的にそんな変わってませんが、インデックスを取得するとかをしなくなったので、だいぶわかりやすくなったのではないかと思っています。<br />ただマップがマップとして読めない感はありますね…キーは内部的にリストとして扱われているので、括弧でくくってやるとちょっとはわかりやすくなるかな…うーん。</p> <h2>まとめ</h2> <p>とりあえずマップライクな処理を置換えても問題ないことがわかりました。他にもマップが使えるところがありますが、そちらはこれほどストレートフォワードではないので、また次回に。<br />えっ、次回…?</p> <h2>補足:<code>-<var>prefixed</var>-linear-gradient()</code>いるかい?</h2> <p>今回は<code>linear-gradient()</code>から<code>-webkit-linear-gradient()</code>などの接頭辞版の構文互換の記述を吐き出すmixinを書きましたが、標準の構文がサポートされてからけっこう経ちます。</p> <p>一番サポートが遅かったのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/WebKit">WebKit</a>なのですが、こちらは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a> 7.0からサポートされています。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a> 6.0以前のサポートによって入れるか入れないかを決めてもよいのではないかと。あるいは<code>-webkit-gradient()</code>を吐き出すなら、特に入れなくてもいいのではないかと思います。</p> myakura WOFF 2.0 Evaluation ReportとBrotli hatenablog://entry/12921228815717847472 2014-02-05T02:26:08+09:00 2014-02-05T02:26:08+09:00 いつだったかにWOFF2のことを書いた。 WebFonts WGのrecharter: より高い圧縮率を備えたWOFF 2.0の検討 タイトルかたいな! その後どうなったのかなと思いつつもめんどくて調べてなかったんだけど、1月末にWOFF 2.0 Evaluation Reportというのが出た。WOFF2で検討されている圧縮の仕組みなどについて調べたレポートとのこと。 Transition request: First public working draft of WOFF 2.0 Evaluation Report WOFF 2.0 Evaluation Report 以下、2013年夏… <p>いつだったかにWOFF2のことを書いた。</p> <ul> <li><a href="http://myakura.hatenablog.com/entry/2012/06/18/015130">WebFonts WGのrecharter: より高い圧縮率を備えたWOFF 2.0の検討</a></li> </ul> <p>タイトルかたいな!</p> <p>その後どうなったのかなと思いつつもめんどくて調べてなかったんだけど、1月末にWOFF 2.0 Evaluation Reportというのが出た。WOFF2で検討されている圧縮の仕組みなどについて調べたレポートとのこと。</p> <ul> <li><a href="http://lists.w3.org/Archives/Public/public-webfonts-wg/2014Jan/0016.html">Transition request: First public working draft of WOFF 2.0 Evaluation Report</a></li> <li><a href="http://www.w3.org/Fonts/WG/WOFF2ER/">WOFF 2.0 Evaluation Report</a></li> </ul> <p>以下、2013年夏くらいからの話題なので新しくないよ。</p> <h2 id="lzma"><a class="keyword" href="http://d.hatena.ne.jp/keyword/LZMA">LZMA</a>はやめたらしい</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>によってWOFF 2.0の元になる仕組みが提案された当初、圧縮<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>は<a class="keyword" href="http://d.hatena.ne.jp/keyword/LZMA">LZMA</a>を使うことになっていた。ただ、高圧縮率の犠牲としてえらい圧縮時間とメモリ使用量が必要ということがわかったので、その採用はなくなったとのこと。ある計測結果によると圧縮にかかる時間が<a class="keyword" href="http://d.hatena.ne.jp/keyword/gzip">gzip</a>の5倍以上、展開時のメモリ使用量が2倍くらいだったそう。</p> <p>Webフォントはサブセットを配布しないのなら一度圧縮するだけで済むけれど、展開時のメモリ消費量は気になる。とくに世の中がモバイルモバイルしている中でこれはだめだったんだろう。</p> <p>ほかにも、<a class="keyword" href="http://d.hatena.ne.jp/keyword/LZMA">LZMA</a>の仕様がない(リファレンスコードを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D0%A1%BC%A5%B9%A5%A8%A5%F3%A5%B8%A5%CB%A5%A2%A5%EA%A5%F3%A5%B0">リバースエンジニアリング</a>するしかない)、IP関連でロイヤリティフリーにできる保証がないということも問題になったよう。仕様があるって大事なんだね……</p> <h2 id="brotli">Brotli登場</h2> <p>代わりとなったのが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>内部でDEFLATEをベースにしたBrotliというもの。昨年<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>から出たZopfliやWebP Loslessを作った人たちによるものらしい。</p> <ul> <li><a href="https://docs.google.com/presentation/d/1aigINmRR7fw_ml8rz0rJ3NTv08Qb3n6lZ_qvmxo8CzQ/present">WOFF2: Compression update</a></li> <li><a href="http://lists.w3.org/Archives/Public/public-webfonts-wg/2013Oct/att-0008/Brotli_Compression_Algortihm_-_motivation.pdf">(PDF) Brotli Compression Algorithm motivation</a></li> <li><a href="https://code.google.com/p/font-compression-reference/">font-compression-reference - Reference code for new font compression</a>(Brotliの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%DD%A5%B8%A5%C8%A5%EA">レポジトリ</a>)</li> <li><a href="https://code.google.com/p/font-compression-reference/source/browse/brotli/brotlispec.txt">brotlispec.txt</a>(仕様)</li> </ul> <p>Evaluation Reportによると<a class="keyword" href="http://d.hatena.ne.jp/keyword/LZMA">LZMA</a>にはやや劣るけれど、フットプリントは半分近くになるらしい。それでもWOFF1と比べて大きいけれど<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%EC%A1%BC%A5%C9%A5%AA%A5%D5">トレードオフ</a>なのかと。</p> <p>実装も<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>にすでにフラグ付きで入ってるらしい。知らなんだ。</p> <ul> <li><a href="https://code.google.com/p/chromium/issues/detail?id=307828">Issue 307828 - chromium - Use Brotli Compression Algorithm for WOFF 2.0</a></li> </ul> <p>今後はBrotliの標準化(<a class="keyword" href="http://d.hatena.ne.jp/keyword/IETF">IETF</a>?)と平行してWOFF2を標準化するらしい。いつくらいになるのでしょうねえ。</p> <h2 id="web">余談:Webでの利用は?</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Mozilla">Mozilla</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CB%A5%E5%A1%BC%A5%B9%A5%B0%A5%EB%A1%BC%A5%D7">ニュースグループ</a>でも取り上げられていて、そこではフォントだけではなくて、HTTPとかWeb全般に使えるのではというコメントつきで紹介されている。</p> <p><a href="https://groups.google.com/forum/#!topic/mozilla.dev.platform/CBhSPWs3HS8">Introducing Brotli - an alternative to LZMA - Google Groups</a></p> <p>とくに議論が発展してないけれど。新しいものを導入するとなるとだいたい切ない話になるので誰も入ってこないのだろうか。</p> myakura システムの文字サイズを取得できないものか hatenablog://entry/12921228815717614269 2014-01-31T21:07:17+09:00 2014-01-31T23:13:33+09:00 80歳の方にiPad Airを使わせてみた方のエントリを読んだ。 実録・80歳の祖父母にiPadを贈った話 | ポッケのなかみ 母とNexus 7 ちょうど年末年始の帰省時に母(60くらいだったかな?)にNexus 7(2012年モデル)を渡したのだけど、このエントリにある「ボタンはしっかりと押さないとね!」というのがあって困った。画面上じゃなくて電源ボタンも無意識に長押しになるので電源オフにするダイアログが出る。実家から戻るときにはだいぶ良くなってたけど、タップはぎこちなかった。慣れてくれるといいな。 あと面白かったのが、アプリアイコンとブックマークを混同していたというか同一視してたこと。「… <p>80歳の方に<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPad">iPad</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Air">Air</a>を使わせてみた方のエントリを読んだ。</p> <ul> <li><a href="http://www.pocke.co.jp/blog/private/present-ipad-grandparents/">実録・80歳の祖父母にiPadを贈った話 | ポッケのなかみ</a></li> </ul> <h2>母と<a class="keyword" href="http://d.hatena.ne.jp/keyword/Nexus%207">Nexus 7</a></h2> <p>ちょうど年末年始の帰省時に母(60くらいだったかな?)に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Nexus%207">Nexus 7</a>(2012年モデル)を渡したのだけど、このエントリにある「ボタンはしっかりと押さないとね!」というのがあって困った。画面上じゃなくて電源ボタンも<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CC%B5%B0%D5">無意</a>識に長押しになるので電源オフにするダイアログが出る。実家から戻るときにはだいぶ良くなってたけど、タップはぎこちなかった。慣れてくれるといいな。</p> <p>あと面白かったのが、アプリアイコンとブックマークを混同していたというか同一視してたこと。「ニュースを見たい」とアプリ一覧を指して言って「ほえ?」となった。アプリ一覧はできないけど、ちょうど<a href="http://chrome.blogspot.jp/2014/01/more-web-more-savings-with-chrome-for.html">Chromeがメニューからホームスクリーンに登録できるようになった</a>ので、それを教えてあげた。ホームスクリーンがアイコンだらけにならないといいけれど。</p> <p>しかし、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a>のデスクトップを見たところWebサイトへのショートカットがばかすかあるわけでもなく、なんで<a class="keyword" href="http://d.hatena.ne.jp/keyword/Nexus%207">Nexus 7</a>でそんな認識になったのかわからない。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>はまたアプリ一覧とホームスクリーンがあるのでややこしいよね。<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPad">iPad</a>だったらまた違う反応をしてたのかな。</p> <p> 他にも面白かった…というかめんどかったのが、半透明のグレーのやつをオーバーレイさせる系の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a>を読みもせずすっとばすこと。「えっえっ」って言って一番目立つ色のボタンを押しちゃって<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a>終了という。わかんないと言われてもこっちだって見てないし…アプリ詳細からデータ削除してもう一回やりなおしたりとか。あれ系を採用する場合にはぜひとも<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a>をやり直すオプションがほしい。</p> <h2>システムの文字サイズが反映されないアプリがかなりある</h2> <p>母の観察記はほどほどにして本題を。件のエントリでも触れられていた点が特に気になった。</p> <blockquote> <h4>文字の表示サイズを大きくできる</h4> <p>「太字」「文字を2まわりくらい大きく」な設定にしてきました。だって<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPad">iPad</a>の文字を虫眼鏡を通して読んでいたんですもん…。<br />私が普段コーディングをしながら「ギャアア」と思っている文字サイズ変更機能も、こういう人向けに必要なのですね。知識として知ってはいましたが、「ああ、こういうことなんだー」と思いました(直接的には少々違いますが、概念として)。</p> </blockquote> <p>こちらも<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>の設定から文字サイズを指定できたので、てきとーに大きくしておいた。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>にも設定あるんだけどそっちはどうだったかな…でも<code>-webkit-text-size-adjust</code>設定されてたら意味ない気がするけど。</p> <p>システムの設定はできても、拡大できるのはシステムのサイズを継承してくれるUI周りで、コンテンツ周り?は拡大してくれないアプリが多かった。ピンチズームも効かなくてうーんと思った。</p> <p>ちょっと見てみて、WebView使ってそうなアプリにそういうのが多い感じがした。システムのサイズを取ってくる<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>とかないのだろうか。</p> <h3>IndieUI User Context</h3> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Web%C9%B8%BD%E0">Web標準</a>側にもそういうのは今のところないはずで、構想がIndieUI WGでつくってる<a href="https://dvcs.w3.org/hg/IndieUI/raw-file/default/src/indie-ui-context.html">IndieUI 1.0: User Context</a>にあるくらいか。“feature key”というメディアクエリーの媒体特性みたいなの(たまに媒体特性としても使えるらしくよくわからない)に<code>user-font-size</code>というのがあるのでそれを使えばよいらしい。</p> <pre>// example of settings keys defined within the IndieUI User Context specification. window.userSetting('user-font-size'); // returns computed value in <a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a> pixels, e.g. '16px'</pre> <p>とはいってもまだ構想段階な感じ。TPACのときにあった<a href="http://lists.w3.org/Archives/Public/www-style/2013Nov/0359.html">CSS WGとのジョイントミーティング</a>、<a href="http://www.w3.org/2013/11/11-webapps-minutes.html#item06">WebApps WGとのジョイントミーティング</a>では、ハイ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%C8%A5%E9">コントラ</a>ストモードの検出とか一部の機能については支持があったけど、セキュリティ・プラバシー的な懸念とかもやっぱりあって、まだまだという印象を受けた。</p> <hr /> <p>使えたら使えたで「システムの文字サイズ継承とか…」みたく思ってしまうのだろうけど、読めないよりは崩れてても読めたほうがいいよねえ。</p> myakura Web技術について書くときの媒体の違いを考える hatenablog://entry/12921228815714377803 2013-12-12T18:00:41+09:00 2013-12-12T18:00:41+09:00 このエントリはEditors' & Writers' Advent Calendar 2013の12日目のやつです。 これまでいろんな媒体で、HTMLやらCSSやらに関することを書いて、そして書かせていただいてるので、媒体ごとの違いなどを考えてみました。 ブログ このweblogや過去に書いていたブログ、勤めていたときにお仕事で書いていたWeb標準Blogなど、ぼくが書く技術系のコンテンツのプライマリな媒体はブログです。 ブログのよいところは、好きなときに好きなことを好きなだけ書けるという、書き手中心のところでしょうか。お仕事で書いていたブログについては、会社のコンテンツということもあり多少な… <p>このエントリは<a href="http://www.adventar.org/calendars/59">Editors' &amp; Writers' Advent Calendar 2013</a>の12日目のやつです。</p> <p>これまでいろんな媒体で、HTMLやら<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>やらに関することを書いて、そして書かせていただいてるので、媒体ごとの違いなどを考えてみました。</p> <h2>ブログ</h2> <p>この<a class="keyword" href="http://d.hatena.ne.jp/keyword/weblog">weblog</a>や過去に書いていたブログ、勤めていたときにお仕事で書いていた<a href="http://standards.mitsue.co.jp/">Web標準Blog</a>など、ぼくが書く技術系のコンテンツのプライマリな媒体はブログです。</p> <p>ブログのよいところは、好きなときに好きなことを好きなだけ書けるという、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%F1%A4%AD%BC%EA">書き手</a>中心のところでしょうか。お仕事で書いていたブログについては、会社のコンテンツということもあり多少なりとも内容についての確認などはありましたが、それでも他の媒体と比べて自由度は高いのかなと。</p> <p>いっぽうで悪いところは自由すぎるところでしょうか。タイミングも分量も表現も自由ですので、自重しないと話しの軸もターゲットも容易に見失います。このブログがよい例です。</p> <h2>オンラインメディア</h2> <p>いまは<a href="http://html5experts.jp/">HTML5 Experts.jp</a>でちょくちょく書いて(と言いたいのだけどまだ1本…すみませんすみません)、お仕事では以前<a>Gihyo.jp</a>さんで原稿を書かせていただいたことがあります。これら2つからオンラインメディア全体について語るのはアレなのですが、とりあえず。</p> <p>よい点としては、「メディア」として幅広い読者層がいるだろうということが強みでしょうか。自分のブログよりも広い相手にリーチできるのかなと。</p> <p>わるい点としては、ターゲットを想定しづらいことでしょうか。メディアによって読者層は違うのでしょうが、多くの人が集まるぶん、狭すぎるものは心理的に書きづらく思います。また、広い読者層がいるわけで、自分のキャラが通じないことは意識しないといけないかなと。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%F1%A4%AD%BC%EA">書き手</a>が基本一人の個人ブログだといいのでしょうけど、多くの執筆者が居て、多くの読者がいるメディアでは、それが伝わらず、たとえば毒舌キャラのまま書いたら無駄な炎上を引き起こしたりとか、そういうのが考えられます。何かを伝えたいのに伝わらない、というか変なコミュニケーションミスまで起こってしまうというのは悲劇です。</p> <p>また、メディアによっては掲載日というものの関係から、すぐに発信したいニュース的なものを投稿することが難しくなるでしょう。また、こちらもですが、編集権限がないため、文章は提出する前にかっちりさせなければなりません。こちらは編集者のお仕事でもあるのですが、みなさんが技術にえらく詳しいわけでもないので。ぼくはずぼらなので、このブログなんかは「あとで編集しよっと」と思いながらだらだら書いて公開後にだだっと編集してますが、そういうやり方ができません。</p> <h2>雑誌</h2> <p>雑誌の特集記事や連載をお仕事でさせていただいたことがあります。なかでも<a href="http://book.mynavi.jp/wd/">Web Designing</a>さんにはとてもお世話になりました。</p> <p>雑誌で書くことのよい点は、まず肩書的になんとなく箔がついてくれること。いやらしいですけど、自己紹介とかで書きやすいのです。<br />って、これは書いたことか。</p> <p>書くにあたってよいなと思うのは、物理的な媒体、つまり面積に縛られるので、文字数や図版などを収める工夫をしないといけないことです。文章は推敲が必要だし、図版などは見せ方を気にしないといけない。Webでできないわけではないのですが、強制されるので、ずぼらなぼくみたいな人にはとても効果があります。面倒ではありますが。</p> <p>わるい点は、これは扱うテーマがWebという進みの激しいものというせいもあるのでしょうが、お店に出るまでのディレイがかなりあることです。ニュース的なものは他の媒体に食われてしまうので、書く意味はそこまでなくなります(ニュースに疎い層がターゲットであればいいのかもですが)。また、あまりにパッと湧いて出た話をすぐに拾ってしまうと、その後の話を記事では説明できないので、あまり健康的ではありません。Web Designingでは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Web%C9%B8%BD%E0">Web標準</a>がらみのトピックをとりあげる連載をさせていただいたのですが、何度かこれで失敗したなと思うことがありました。</p> <hr /> <p>ちょっと時間がないので草稿でだしとく。あとでもうちょいいじる。</p> myakura all, initial, unsetでCSSのリセットと継承回避をする hatenablog://entry/12921228815714333431 2013-12-11T18:37:18+09:00 2018-04-16T09:55:03+09:00 追記(2018年4月13日):紹介した機能の実装が進みました(Can I use:allプロパティ、initial、unset)。 一方で文中で取り上げたScoped Stylesheetsは仕様から削除されてしまいました。 このエントリはCSS Property Advent Calendar 2013の10日目のものです。すみませんすみません日付勘違いしてました。ほんと申し訳ありません…… 今回はradial-gradient()のMixin…は作りません。プロパティじゃないしね。ふつうのプロパティと値についてご紹介しようかと。 CSS Cascading & Inheritanceのal… <p><strong>追記(2018年4月13日)</strong>:紹介した機能の実装が進みました(Can I use:<a href="https://caniuse.com/#feat=css-all"><code>all</code>プロパティ</a>、<a href="https://caniuse.com/#feat=css-initial-value"><code>initial</code></a>、<a href="https://caniuse.com/#feat=css-unset-value"><code>unset</code></a>)。</p> <p>一方で文中で取り上げたScoped Stylesheetsは仕様から削除されてしまいました。</p> <hr /> <p>このエントリは<a href="http://www.adventar.org/calendars/57">CSS Property Advent Calendar 2013</a>の10日目のものです。<br />すみませんすみません日付勘違いしてました。ほんと申し訳ありません……</p> <p>今回は<code>radial-gradient()</code>のMixin…は作りません。プロパティじゃないしね。ふつうのプロパティと値についてご紹介しようかと。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a> Cascading &amp; Inheritanceの<code>all</code>, <code>initial</code>, <code>unset</code></h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a> 27あたりから<code>all</code>プロパティと<code>unset</code>値なんてものが実装されました。<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>の<a href="http://dev.w3.org/csswg/css-cascade/">Cascading and Inheritanceモジュール</a>で定義されてるんですが、これを使うとスタイルを局所的にリセットできます。実装した<a class="keyword" href="http://d.hatena.ne.jp/keyword/Mozilla">Mozilla</a>のCameronのエントリが詳しいです。</p> <ul> <li><a href="http://mcc.id.au/blog/2013/10/all-unset">Resetting styles using ‘all: unset’ in Firefox 27</a></li> </ul> <p><code>all</code>は「すべてのプロパティ(※ただし<code>direction</code>と<code>unicode-bidi</code>を除く)」を指します。すべて(※)です。これから定義・実装されるプロパティもすべて<code>all</code>になります(※)。ターンAみたいですね。</p> <p><code>initial</code>, <code>unset</code>は<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>ワイドな値です。<code>initial</code>は初期値(を指定値にする)値で、結構前からいろんなブラウザで実装されています。<code>inherit</code>というのもあります。これは継承値を指定値かつ算出値にするものです。<code>unset</code>というのはその間の子で、継承するプロパティ(<code>font-size</code>やら<code>color</code>やら)については<code>inherit</code>, そうでないものには<code>initial</code>という扱いになります。<code>unset</code>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B9%A5%B1%A1%BC%A5%B9">ユースケース</a>がいまいちわからず、昔何かで読んだ気がするのですが忘れました。とりあえず次に進みます。</p> <h2>スタイルをリセットしたい?</h2> <p>スタイルをリセットしたい場合って、今のところそんなあるようなないようなですが、かなり個人的な背景からそう思うときは多々あります。</p> <p>たとえば、HTMLと<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>の講演スライド。スライド作成ソフトと比べるとまだあんま良くないと思っているのですが、スライド中にWebコンテントを直接埋め込める利点があります。とくにHTMLや<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>についてお話させてもらうので、実際のコンテンツを埋め込めると楽です。</p> <p>埋め込みというと、外部コンテンツを<code>&lt;iframe&gt;</code>で読み込むという手もありますが、複数ファイル作るのが面倒な例などは、インラインで直接書きたいものです。</p> <pre>&lt;div class="example"&gt; &lt;!-- サンプルコードがここに入る --&gt; &lt;/div&gt;</pre> <p>とはいえ、ここで面倒なのが、<code>div.example</code>内のコンテンツが親のスタイルを継承してしまうこと。スライドのスタイルは<a class="keyword" href="http://d.hatena.ne.jp/keyword/10-feet">10-feet</a> UIといいますか、背景と前景の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%C8%A5%E9">コントラ</a>ストをなるべくとる、文字は大きくするなど、デスクトップスクリーンとはまた違う流儀があります。サンプルがどんなものかにもよりますが、そういったスタイルが継承されると上書きすることが面倒です。サンプルはシンプルにゼロから始めたい。ここで<code>all</code>と<code>initial</code>が役立ちます。</p> <pre>&lt;div class="example"&gt; &lt;style scoped&gt; * { all: initial } &lt;/style&gt; &lt;!-- サンプルコードがここに入る --&gt; &lt;/div&gt;</pre> <p><code>&lt;style scoped&gt;</code>を入れて<code>div.example</code>だけに対応するスタイルを書けるようにします。そして最初で<code>all: initial</code>でスタイルをキャンセルすることにより、<code>div.example</code>が親からのスタイルを継承しないようにします。</p> <p>親のスタイルを一部継承したい場合は<code>all: unset</code>でもいいかもしれません。</p> <p><code>display</code>が<code>inline</code>になるのがだるいですね…プロパティごとに<code>initial</code>のがいいかもなあ。</p> <h2>Scoped Stylesheetsの危機</h2> <p>HTML+<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>なスライドで例をインラインで書きたい、というあまりにもニッチな<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B9%A5%B1%A1%BC%A5%B9">ユースケース</a>ですが、<code>all</code>, <code>initial</code> <code>unset</code>の便利さをお分かりいただけたでしょうか。無理かなあ。</p> <p>さて、実装が進めば素敵なHTML+<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>なスライドライフをおくれそうですが、現在Scoped Stylesheetsを消さないかという話が出ていたりします。もともと<a class="keyword" href="http://d.hatena.ne.jp/keyword/HTML5">HTML5</a>でat riskな機能で、現在も<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>でしかリリースされてません。<a href="https://groups.google.com/a/chromium.org/d/topic/blink-dev/JB8nFQXhAuQ/discussion">そんな中blink-devで削除しないという話がでてしまい</a>、あまりいい具合ではありません。Hixieは制作者の要望が大きいことを述べていますが、大きく反対しているわけでもなく、しばらく放置されそう。<a class="keyword" href="http://d.hatena.ne.jp/keyword/HTML5">HTML5</a>からは削除されるかな。</p> <p><code>&lt;style scoped&gt;</code>を使わずとも、スコープさせたい要素の親に<code>id</code>でもふってやればいいのですが、サンプルコードまわりをひとまとめにしときたいんだよなあ。</p> myakura WebプラットフォームのこれからとExtensible Web hatenablog://entry/12921228815714200302 2013-12-08T23:50:00+09:00 2013-12-09T01:22:39+09:00 この記事はFrontrend Advent Calendar 2013の8日目の記事です。 昨日岐阜県にてHTML5 Conference 2013 in Gifuというイベントがありまして、そちらでWebプラットフォーム動向についてお話させていただきました。スライドはこちら。 2013年のWebプラットフォーム 相変わらずふんにゃりした話しかできず心苦しい。 Extensible Webが実行に移った2013年 今年はOperaのWebKitChromium移行、Blink登場、IE11で互換機能を非推奨に、など、ブラウザの動きが大きくて、あまりWeb標準周りで大きなニュースがなかったように… <p>この記事は<a href="http://www.adventar.org/calendars/62">Frontrend Advent Calendar 2013</a>の8日目の記事です。</p> <p>昨日岐阜県にて<a href="https://www.softopia.or.jp/training/2013html5/">HTML5 Conference 2013 in Gifu</a>というイベントがありまして、そちらでWebプラットフォーム動向についてお話させていただきました。スライドはこちら。</p> <ul> <li><a href="https://docs.google.com/presentation/d/1msQeS1xY_oMCLQMwceB_xSFv58TtFHOT4t0amArs_jg/edit?usp=sharing">2013年のWebプラットフォーム</a></li> </ul> <p>相変わらずふんにゃりした話しかできず心苦しい。</p> <h2>Extensible Webが実行に移った2013年</h2> <p>今年は<a href="http://myakura.hatenablog.com/entry/2013/02/14/000419">Operaの<s>WebKit</s>Chromium移行</a>、<a href="http://myakura.hatenablog.com/entry/2013/04/07/111238">Blink登場</a>、<a href="http://myakura.hatenablog.com/entry/2013/04/04/195122">IE11で互換機能を非推奨に</a>、など、ブラウザの動きが大きくて、あまり<a class="keyword" href="http://d.hatena.ne.jp/keyword/Web%C9%B8%BD%E0">Web標準</a>周りで大きなニュースがなかったように思います。あったらあったで面倒なんですが(たぶん良いニュースはない)。ただ、思ったよりずっと動きが速いなと思ったのが、<a href="http://extensiblewebmanifesto.org/">Extensible Web</a>関連です。</p> <p>「低レベルなのモデル・<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>をつくり、高レベルな機能はその上で表現可能とする」というのがExtensible Webの基本的な考えと認識してますが、その構想が動きを伴って大きく進められたような気がするなと思いました。Service Workersのハイプ化や策定中のPromisesを導入した<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>仕様の登場とかとかを見ると、とくにそう感じます。また、Polymerに見られるWeb Componentsまわりのスタックを一部Prolyfillとして実装する取り組みなど、実践しはじめているのも見られます。とくにProlyfillによる試験実装は、これからのWeb開発・標準化において一つの側面となるのではないかと思っていて、注目しています。</p> <h2>マクロな標準化とミクロな標準化</h2> <p>スライドの中で、こうしたExtensible Webなアプローチが進むことにより「ミクロな標準化」が出てくるのかなと予想を書きました。マクロ・ミクロという言葉の使い方がしっくり来ないまま使っているのでまだもやもやしてるのですが、標準化団体による標準化を「マクロな標準化」、Web開発者コミュニティによる高レベル<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の開発・普及活動を「ミクロな標準化」と呼んでいます。</p> <p>低レベルな<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>に集中しようという流れの背景は、高レベルな<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を定義しても実装においてそのモデルや低レベルなところをさらう必要が出てくる、それをしないとしょうもない機能になってしまう(例:AppCache)ことへの反省がひとつ、そして「すべての望みは標準化によって解決するものではない」という認識の改めがもうひとつあるのかと思っています。ある意味標準化団体が「投げた」のかもしれません。</p> <p>とはいえ、低レベルなところを作ってくれるおかげで、高レベルなものは表現しやすくなるでしょう。相互運用性も高まるのではないかと期待しています。さらには開発者が作った高レベルな機能が広まった際には、それを「マクロ」側で標準化することもそれなりに容易いのかと。コードが仕様になりますから。</p> <p>ミクロな標準化とやらが<a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a>などとどう違うのかですが、標準化団体との関係が違うかなと考えてます。高レベルな<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>が作られることをふまえた低レベルなモデル・<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>という方針があることで、標準化団体へのアップストリームというパスができたことが大きなことだと思っています。これまで開発者と標準化団体・ベンダーはどうにも接点があるようで弱くて、あまり協力して標準化という流れにはなってない印象があります。これが短期的に変わるとは思いませんが、開発者が自分たちの欲しい機能を作れるというオプションが用意されたので、変な摩擦が少なくなれば健康的かなと。</p> <h2>低レベル指向の落とし穴?</h2> <p>懸念があるとするならば、まず表現においてはExtensibleな部分が少ないというところ。ええと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>での低レベルなモデルが存在していないこととCSSOMが貧弱ということでしょうか。<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a> Grid Layoutあたりが来ればもうちょっと良くなるのかとは思っていますが(Blinkでちまちま実装が進んでいるのも、Extensible Webのひとつとして考えてるのかなと)。</p> <p>あとは、高レベルな機能の設計ができる人がどれくらいいるのかというところ。Web Componentsなどでオレオレな要素や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>が定義できるようにはなるのでしょうが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a>のように広く普及するようなくらいのものが出てくるのか、作れる人がいるのか。高レベルな機能の開発者が不在なのに低レベルなものに終始すると、それはそれでWebの発展を妨げるかなと。</p> <p>とはいっても、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Apple">Apple</a>のように高レベルでdeclarativeなのが好きなところもあるので、これから出るものがすべて低レベルでimperativeというわけではないと思いますが。</p> <h2>おわりに</h2> <p>なんだかスライドの反芻しかできてない気がするので、とりあえずここで一旦切ります。Extensible Webについては、TAGと新しい<a class="keyword" href="http://d.hatena.ne.jp/keyword/GoF">GoF</a>の登場、Layeringという考えの提唱、Extensible Web Manifestoなどの登場などいろんな契機があったのですが考えがまとまらず書けなかったので、ようやく書けたのでうれしいです。といっても、まだまとまってないところもあるし、うまく説明もできてないですが……</p> <p>PromisesやService Workers, Web Componentsなど個々の技術についても、ぼちぼち何か書いていきたいですね。とくに今はWeb Componentsと静的なWebサイトの部品、文書構造との関連についていろいろ気になっているところです。ではでは。</p> myakura SVGヤバイ 2013冬 hatenablog://entry/12921228815713262734 2013-11-27T19:08:57+09:00 2018-03-14T11:27:18+09:00 Chrome 31がStableになって久しい。何が変わったのか思い出せないんだけど、ひとつだけ覚えてるのがこちら。 (@156422) - b87d44f — Allow SVG images to not taint the canvas with drawImage/drawPattern WebKitのパッチをマージしたものらしい。ちょっとずつ離れているらしいけど、まだお互い共有できるパッチもあるんだね。 さて、このパッチによって、CanvasでSVG画像をdrawImage()などで描画したとき、条件によってはそのCanvasがtaintされなくなった。 Tainted Canvas… <p><a href="http://googlechromereleases.blogspot.jp/2013/11/stable-channel-update.html">Chrome 31がStableに</a>なって久しい。何が変わったのか思い出せないんだけど、ひとつだけ覚えてるのがこちら。</p> <ul> <li><a href="https://chromium.googlesource.com/chromium/blink/+/b87d44f">(@156422) - b87d44f — Allow SVG images to not taint the canvas with drawImage/drawPattern</a></li> </ul> <p><a href="http://trac.webkit.org/changeset/153876">WebKitのパッチ</a>をマージしたものらしい。ちょっとずつ離れているらしいけど、まだお互い共有できるパッチもあるんだね。</p> <p>さて、このパッチによって、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Canvas">Canvas</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>画像を<code>drawImage()</code>などで描画したとき、条件によってはその<a class="keyword" href="http://d.hatena.ne.jp/keyword/Canvas">Canvas</a>がtaintされなくなった。</p> <h2>Tainted <a class="keyword" href="http://d.hatena.ne.jp/keyword/Canvas">Canvas</a>とは</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Canvas">Canvas</a>には<code>drawImage()</code>など、画像を<a class="keyword" href="http://d.hatena.ne.jp/keyword/Canvas">Canvas</a>に描画するメソッドがある。ここで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>とsame-originではないとこにある画像を描画してしまうと、セキュリティ上の都合から<a class="keyword" href="http://d.hatena.ne.jp/keyword/Canvas">Canvas</a>が“tainted”(「汚染」)という扱いになり、<code>getImageData()</code>, <code>toDataURL()</code>, <code>toBlob()</code>などができない。</p> <p>ハックではない正攻法な対策としては、画像の配置場所を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>とsame-originなところにするのが楽か。もしくはCORSのヘッダを設定してその許可したorigin以下に画像を配置し、それから画像に<code>crossorigin</code>属性(DOMの場合は<code>crossOrigin</code>)を指定するなんてやり方もある。詳しくはMDNのドキュメント参照のこと。日本語訳がある。</p> <ul> <li><a href="https://developer.mozilla.org/ja/docs/CORS_Enabled_Image">CORS有効な画像</a></li> <li><a href="https://developer.mozilla.org/ja/docs/Web/HTML/CORS_settings_attributes">CORS設定属性</a></li> </ul> <p>こんなニッチなの誰が訳したんだと思ったら自分だった…記憶がまったくない。</p> <h2>きたない<a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a></h2> <p>さて、originまわりが良くなってもtainted扱いになるなんて場合がある。<a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>画像だ。<a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>は中に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>や画像を書けちゃうので、危ないと判断されて<a class="keyword" href="http://d.hatena.ne.jp/keyword/WebKit">WebKit</a>/Blinkではこれまでどうあがいてもtainted扱いとなっていた。</p> <p>あー説明めんどくさい…と思ってたらgyuqueさんが2年半前に同じことを書かれていた。しかもデモつき。なんと。</p> <ul> <li><a href="http://d.hatena.ne.jp/gyuque/20110510">SVGヤバイ - 最速チュパカブラ研究会</a></li> </ul> <p>今回のパッチで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>画像が内部で画像を呼んでない場合、その<a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>画像を<code>drawImage()</code>で読み込んでもtainted扱いにならなくなった。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a> 31で見てみたところ、一番右の列がすべて「OK」となったのを確認。</p> <p><img class="hatena-fotolife" src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/myakura/20131127/20131127190550.png" alt="図:単純なSVG画像をdrawImage()してもtainted扱いにならなくなった例" /></p> <p>マミさんは死んだ。</p> <p>例で使われている画像的には良い気がしないけど、Webプラットフォーム的には良い変更だ。</p> <p>試してないけど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>画像の中に<code>&lt;svg:image&gt;</code>があるとアウトになるんだろう。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Gecko">Gecko</a>ではだいぶ前からOKだったらしい</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>で見たところこちらもOK(マミさんは死ぬけど)。2011年5月時点では<a class="keyword" href="http://d.hatena.ne.jp/keyword/Gecko">Gecko</a>でもダメだったようだけど、<a href="https://hg.mozilla.org/mozilla-central/rev/89a8e26f1df0">Geckoでは2011年末に修正</a>され、<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/11#section_4">Firefox 11から使えていた</a>らしい。今回Blinkもサポートされるのでカバー範囲が広がったけど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a> 8になるだろう。来年かー</p> myakura