<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id/>
    <title>Tomoyuki Kashiro's Blog</title>
    <updated>2023-01-09T08:28:39.520Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <author>
        <name>Tomoyuki Kashiro</name>
        <uri>https://tomoyukikashiro.me</uri>
    </author>
    <link rel="self" href="/rss.xml"/>
    <subtitle>A Web developer in Tokyo focus on React/Vue and Rails/Django. Google Mobile Web Specialist / Google Analytics Individual Qualification</subtitle>
    <rights>All rights reserved 2023, Tomoyuki Kashiro</rights>
    <entry>
        <title type="html"><![CDATA[Use Page Object Pattern in React Component Tests]]></title>
        <id>en-US-page-object-pattern-in-react-component-tests</id>
        <link href="https://blog.tomoyukikashiro.me/post/page-object-pattern-in-react-component-tests"/>
        <updated>2022-08-14T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[It might be worthy to use page object pattern in react component as well as E2E tests to make tests readability and maintainability better.]]></summary>
        <content type="html"><![CDATA[<p>My understanding is that readability and maintainability are domains which should be put high priority in software tests. To achieve this, using <code>Page Object Pattern</code> might be a good help not only in E2E tests but also React Component tests.<h2 id=what-is-the-page-object-pattern><a href=#what-is-the-page-object-pattern aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>What is the Page Object Pattern</h2><p><a href=https://webdriver.io/docs/pageobjects/>https://webdriver.io/docs/pageobjects/</a><p>Page Object Pattern is one of the software programming principle which encapsulate page manipulation logic that tend to harm readability and maintainability in software tests.<p>Software test involves two kinds of cods below.<ul><li>test code : e.g. Shows error messages when invalid email is typed in form.<li>manipulation code to reproduce test situation : e.g. Shows page then type email</ul><p>Page Object Pattern aims to move the latter codes to page class, which is called Page Object, to help software engineers read and write the former codes easily.<h2 id=the-example-of-page-object-pattern><a href=#the-example-of-page-object-pattern aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>The example of Page Object Pattern</h2><p>Let’s see <a href=https://webdriver.io/docs/pageobjects/>https://webdriver.io/docs/pageobjects/</a><pre class=language-js><code class="language-js code-highlight"><span class=code-line><span class="token comment">// Page class has E2E test instance which comes from test library such as selenium.</span>
</span><span class=code-line><span class="token keyword module">import</span> <span class="token imports"><span class="token maybe-class-name">Page</span></span> <span class="token keyword module">from</span> <span class="token string">'./page'</span>
</span><span class=code-line>
</span><span class=code-line><span class="token keyword">class</span> <span class="token class-name">LoginPage</span> <span class="token keyword">extends</span> <span class="token class-name">Page</span> <span class="token punctuation">{</span>
</span><span class=code-line>
</span><span class=code-line>    <span class="token comment">// Defines some functions to manipulate page to reproduce test situation.</span>
</span><span class=code-line>    <span class="token keyword">get</span> <span class="token function">username</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword control-flow">return</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'#username'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span>
</span><span class=code-line>    <span class="token keyword">get</span> <span class="token function">password</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword control-flow">return</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'#password'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span>
</span><span class=code-line>    <span class="token keyword">get</span> <span class="token function">submitBtn</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword control-flow">return</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'form button[type="submit"]'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span>
</span><span class=code-line>    <span class="token keyword">get</span> <span class="token function">flash</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword control-flow">return</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'#flash'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span>
</span><span class=code-line>    <span class="token keyword">get</span> <span class="token function">headerLinks</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword control-flow">return</span> <span class="token function">$$</span><span class="token punctuation">(</span><span class="token string">'#header a'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line>    <span class="token keyword">async</span> <span class="token function">open</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class=code-line>        <span class="token keyword control-flow">await</span> <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function property-access method">open</span><span class="token punctuation">(</span><span class="token string">'login'</span><span class="token punctuation">)</span>
</span><span class=code-line>    <span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line>    <span class="token keyword">async</span> <span class="token function">submit</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class=code-line>        <span class="token keyword control-flow">await</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token property-access">submitBtn</span><span class="token punctuation">.</span><span class="token function property-access method">click</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class=code-line>    <span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token keyword module">export</span> <span class="token keyword module">default</span> <span class="token keyword">new</span> <span class="token class-name">LoginPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span></code></pre><p>By using this page instance to prepare test cases, we can make test codes simple.<pre class=language-js><code class="language-js code-highlight"><span class=code-line><span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'should deny access with wrong creds'</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator arrow">=></span> <span class="token punctuation">{</span>
</span><span class=code-line>    <span class="token keyword control-flow">await</span> <span class="token maybe-class-name">LoginPage</span><span class="token punctuation">.</span><span class="token function property-access method">open</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class=code-line>    <span class="token keyword control-flow">await</span> <span class="token maybe-class-name">LoginPage</span><span class="token punctuation">.</span><span class="token property-access">username</span><span class="token punctuation">.</span><span class="token function property-access method">setValue</span><span class="token punctuation">(</span><span class="token string">'foo'</span><span class="token punctuation">)</span>
</span><span class=code-line>    <span class="token keyword control-flow">await</span> <span class="token maybe-class-name">LoginPage</span><span class="token punctuation">.</span><span class="token property-access">password</span><span class="token punctuation">.</span><span class="token function property-access method">setValue</span><span class="token punctuation">(</span><span class="token string">'bar'</span><span class="token punctuation">)</span>
</span><span class=code-line>    <span class="token keyword control-flow">await</span> <span class="token maybe-class-name">LoginPage</span><span class="token punctuation">.</span><span class="token function property-access method">submit</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class=code-line>
</span><span class=code-line>    <span class="token keyword control-flow">await</span> <span class="token function">expect</span><span class="token punctuation">(</span><span class="token maybe-class-name">LoginPage</span><span class="token punctuation">.</span><span class="token property-access">flash</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function property-access method">toHaveText</span><span class="token punctuation">(</span><span class="token string">'Your username is invalid!'</span><span class="token punctuation">)</span>
</span><span class=code-line><span class="token punctuation">}</span><span class="token punctuation">)</span>
</span></code></pre><h2 id=how-to-use-page-object-pattern-in-react-component-tests><a href=#how-to-use-page-object-pattern-in-react-component-tests aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>How to use Page Object Pattern in React Component tests</h2><pre class=language-tsx><code class="code-highlight language-tsx"><span class=code-line><span class="token keyword">import</span> <span class="token keyword">type</span> <span class="token punctuation">{</span> <span class="token maybe-class-name">ComponentProps</span> <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token keyword">import</span> <span class="token imports"><span class="token punctuation">{</span> render <span class="token punctuation">}</span></span> <span class="token keyword">from</span> <span class="token string">"@testing-library/react"</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token keyword">import</span> <span class="token imports">userEvent</span> <span class="token keyword">from</span> <span class="token string">"@testing-library/user-event"</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token keyword">import</span> <span class="token imports"><span class="token maybe-class-name">LoginForm</span></span> <span class="token keyword">from</span> <span class="token string">"./LoginForm"</span><span class="token punctuation">;</span>
</span><span class=code-line>
</span><span class=code-line><span class="token keyword">type</span> <span class="token class-name">Props</span> <span class="token operator">=</span> <span class="token maybe-class-name">ComponentProps</span><span class="token operator">&lt;</span><span class="token keyword">typeof</span> <span class="token maybe-class-name">LoginForm</span><span class="token operator">></span>
</span><span class=code-line>
</span><span class=code-line><span class="token keyword">const</span> setup <span class="token operator">=</span> <span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token maybe-class-name">Props</span> <span class="token operator arrow">=></span> <span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token keyword">const</span> <span class="token punctuation">{</span> getByRole<span class="token punctuation">,</span> getByLabelText<span class="token punctuation">,</span> getByText <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">render</span><span class="token punctuation">(</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">LoginForm</span></span> <span class="token spread"><span class="token punctuation">{</span><span class="token operator spread">...</span>props<span class="token punctuation">}</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line>  <span class="token keyword">return</span> <span class="token punctuation">{</span>
</span><span class=code-line>    <span class="token function function-variable">typeEmail</span><span class="token operator">:</span> <span class="token punctuation">(</span>email<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token operator arrow">=></span> userEvent<span class="token punctuation">.</span><span class="token function property-access method">type</span><span class="token punctuation">(</span><span class="token function">getByLabelText</span><span class="token punctuation">(</span><span class="token string">"email"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> email<span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class=code-line>    getByText<span class="token punctuation">,</span>
</span><span class=code-line>    <span class="token function function-variable">submit</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator arrow">=></span> userEvent<span class="token punctuation">.</span><span class="token function property-access method">click</span><span class="token punctuation">(</span><span class="token function">getByRole</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class=code-line>  <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class=code-line>
</span><span class=code-line>
</span><span class=code-line><span class="token function">it</span><span class="token punctuation">(</span><span class="token string">"When email typed is invalid, shows error message."</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator arrow">=></span> <span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token keyword">const</span> utils <span class="token operator">=</span> <span class="token function">setup</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line>  utils<span class="token punctuation">.</span><span class="token function property-access method">typeEmail</span><span class="token punctuation">(</span><span class="token string">"invalidemail"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line>  utils<span class="token punctuation">.</span><span class="token function property-access method">submit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line>
</span><span class=code-line>  <span class="token function">expect</span><span class="token punctuation">(</span>utils<span class="token punctuation">.</span><span class="token function property-access method">getByText</span><span class="token punctuation">(</span><span class="token string">"Email is not correct."</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span> <span class="token function property-access method">toBeInTheDocument</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre>]]></content>
        <published>2022-08-13T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Page Object Pattern を React Component テストでも利用する]]></title>
        <id>ja-JP-page-object-pattern-in-react-component-tests</id>
        <link href="https://blog.tomoyukikashiro.me/ja-JP/post/page-object-pattern-in-react-component-tests"/>
        <updated>2022-08-13T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[E2E テストで利用する Page Object Pattern を Component テストでも利用することで可読性の高いテストがかけるのではないだろうか？]]></summary>
        <content type="html"><![CDATA[<p>E2E テストで利用する Page Object Pattern を Component テストでも利用することで可読性の高いテストがかけるのではないだろうかと思ってメモに残します。<h2 id=page-object-pattern-とは><a href=#page-object-pattern-とは aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Page Object Pattern とは</h2><p><a href=https://webdriver.io/docs/pageobjects/>https://webdriver.io/docs/pageobjects/</a><p>E2E テストでは、以下2つのコードが混在することになり、テストがしたいことがぱっと見でわかりにくいことがあります。<ul><li>テストコード（例：フォームにinvalidなemailが入力されている場合、エラーが表示すること<li>テストするためにページを操作するコード（例：フォームに文字を入力または、フォームのエラー文字を取得）</ul><p>さらに、 <code>テストするためにページを操作するコード</code> が点在していると、フォームの id や name を修正しただけで、点在するコードをすべて修正することになりメンテナンス性も損なわれがちです。<p>Page Object Pattern では、<code>テストするためにページを操作するコード</code> を オブジェクトでひとまとめにして、使い回すことで、テストの可読性やメンテナンス性を上げる方法です。<h2 id=page-object-pattern-の例><a href=#page-object-pattern-の例 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Page Object Pattern の例</h2><p><a href=https://webdriver.io/docs/pageobjects/>https://webdriver.io/docs/pageobjects/</a> の例をそのまま利用すると、、<pre class=language-js><code class="language-js code-highlight"><span class=code-line><span class="token comment">// selenium など E2E テストライブのインスタンスを保持する親クラス</span>
</span><span class=code-line><span class="token keyword module">import</span> <span class="token imports"><span class="token maybe-class-name">Page</span></span> <span class="token keyword module">from</span> <span class="token string">'./page'</span>
</span><span class=code-line>
</span><span class=code-line><span class="token keyword">class</span> <span class="token class-name">LoginPage</span> <span class="token keyword">extends</span> <span class="token class-name">Page</span> <span class="token punctuation">{</span>
</span><span class=code-line>
</span><span class=code-line>    <span class="token comment">// ログインページのテストで使う `テストするためにページを操作するコード`</span>
</span><span class=code-line>    <span class="token keyword">get</span> <span class="token function">username</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword control-flow">return</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'#username'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span>
</span><span class=code-line>    <span class="token keyword">get</span> <span class="token function">password</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword control-flow">return</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'#password'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span>
</span><span class=code-line>    <span class="token keyword">get</span> <span class="token function">submitBtn</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword control-flow">return</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'form button[type="submit"]'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span>
</span><span class=code-line>    <span class="token keyword">get</span> <span class="token function">flash</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword control-flow">return</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'#flash'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span>
</span><span class=code-line>    <span class="token keyword">get</span> <span class="token function">headerLinks</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword control-flow">return</span> <span class="token function">$$</span><span class="token punctuation">(</span><span class="token string">'#header a'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line>    <span class="token keyword">async</span> <span class="token function">open</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class=code-line>        <span class="token keyword control-flow">await</span> <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function property-access method">open</span><span class="token punctuation">(</span><span class="token string">'login'</span><span class="token punctuation">)</span>
</span><span class=code-line>    <span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line>    <span class="token keyword">async</span> <span class="token function">submit</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class=code-line>        <span class="token keyword control-flow">await</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token property-access">submitBtn</span><span class="token punctuation">.</span><span class="token function property-access method">click</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class=code-line>    <span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token keyword module">export</span> <span class="token keyword module">default</span> <span class="token keyword">new</span> <span class="token class-name">LoginPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span></code></pre><p>これを、テストコードで使いまわしますことで、 <code>テストするためにページを操作するコード</code> がシンプルになり、テストコードが読みやすく、またページに変更があっても Page Object を修正するだけで済み、テストコードへの影響を抑えることができます。<pre class=language-js><code class="language-js code-highlight"><span class=code-line><span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'should deny access with wrong creds'</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator arrow">=></span> <span class="token punctuation">{</span>
</span><span class=code-line>    <span class="token keyword control-flow">await</span> <span class="token maybe-class-name">LoginPage</span><span class="token punctuation">.</span><span class="token function property-access method">open</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class=code-line>    <span class="token keyword control-flow">await</span> <span class="token maybe-class-name">LoginPage</span><span class="token punctuation">.</span><span class="token property-access">username</span><span class="token punctuation">.</span><span class="token function property-access method">setValue</span><span class="token punctuation">(</span><span class="token string">'foo'</span><span class="token punctuation">)</span>
</span><span class=code-line>    <span class="token keyword control-flow">await</span> <span class="token maybe-class-name">LoginPage</span><span class="token punctuation">.</span><span class="token property-access">password</span><span class="token punctuation">.</span><span class="token function property-access method">setValue</span><span class="token punctuation">(</span><span class="token string">'bar'</span><span class="token punctuation">)</span>
</span><span class=code-line>    <span class="token keyword control-flow">await</span> <span class="token maybe-class-name">LoginPage</span><span class="token punctuation">.</span><span class="token function property-access method">submit</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</span><span class=code-line>
</span><span class=code-line>    <span class="token keyword control-flow">await</span> <span class="token function">expect</span><span class="token punctuation">(</span><span class="token maybe-class-name">LoginPage</span><span class="token punctuation">.</span><span class="token property-access">flash</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function property-access method">toHaveText</span><span class="token punctuation">(</span><span class="token string">'Your username is invalid!'</span><span class="token punctuation">)</span>
</span><span class=code-line><span class="token punctuation">}</span><span class="token punctuation">)</span>
</span></code></pre><h2 id=react-component-テストで-page-object-pattern-を-利用する><a href=#react-component-テストで-page-object-pattern-を-利用する aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>React Component テストで Page Object Pattern を 利用する</h2><pre class=language-tsx><code class="code-highlight language-tsx"><span class=code-line><span class="token keyword">import</span> <span class="token keyword">type</span> <span class="token punctuation">{</span> <span class="token maybe-class-name">ComponentProps</span> <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token keyword">import</span> <span class="token imports"><span class="token punctuation">{</span> render <span class="token punctuation">}</span></span> <span class="token keyword">from</span> <span class="token string">"@testing-library/react"</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token keyword">import</span> <span class="token imports">userEvent</span> <span class="token keyword">from</span> <span class="token string">"@testing-library/user-event"</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token keyword">import</span> <span class="token imports"><span class="token maybe-class-name">LoginForm</span></span> <span class="token keyword">from</span> <span class="token string">"./LoginForm"</span><span class="token punctuation">;</span>
</span><span class=code-line>
</span><span class=code-line><span class="token keyword">type</span> <span class="token class-name">Props</span> <span class="token operator">=</span> <span class="token maybe-class-name">ComponentProps</span><span class="token operator">&lt;</span><span class="token keyword">typeof</span> <span class="token maybe-class-name">LoginForm</span><span class="token operator">></span>
</span><span class=code-line>
</span><span class=code-line><span class="token keyword">const</span> setup <span class="token operator">=</span> <span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token maybe-class-name">Props</span> <span class="token operator arrow">=></span> <span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token keyword">const</span> <span class="token punctuation">{</span> getByRole<span class="token punctuation">,</span> getByLabelText<span class="token punctuation">,</span> getByText <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">render</span><span class="token punctuation">(</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">LoginForm</span></span> <span class="token spread"><span class="token punctuation">{</span><span class="token operator spread">...</span>props<span class="token punctuation">}</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line>  <span class="token keyword">return</span> <span class="token punctuation">{</span>
</span><span class=code-line>    <span class="token function function-variable">typeEmail</span><span class="token operator">:</span> <span class="token punctuation">(</span>email<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token operator arrow">=></span> userEvent<span class="token punctuation">.</span><span class="token function property-access method">type</span><span class="token punctuation">(</span><span class="token function">getByLabelText</span><span class="token punctuation">(</span><span class="token string">"email"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> email<span class="token punctuation">)</span><span class="token punctuation">,</span>
</span><span class=code-line>    getByText<span class="token punctuation">,</span>
</span><span class=code-line>    <span class="token function function-variable">submit</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator arrow">=></span> userEvent<span class="token punctuation">.</span><span class="token function property-access method">click</span><span class="token punctuation">(</span><span class="token function">getByRole</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span><span class=code-line>  <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class=code-line>
</span><span class=code-line>
</span><span class=code-line><span class="token function">it</span><span class="token punctuation">(</span><span class="token string">"invalidなemailの場合、エラーを表示する。"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator arrow">=></span> <span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token keyword">const</span> utils <span class="token operator">=</span> <span class="token function">setup</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line>  utils<span class="token punctuation">.</span><span class="token function property-access method">typeEmail</span><span class="token punctuation">(</span><span class="token string">"invalidemail"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line>  utils<span class="token punctuation">.</span><span class="token function property-access method">submit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line>
</span><span class=code-line>  <span class="token function">expect</span><span class="token punctuation">(</span>utils<span class="token punctuation">.</span><span class="token function property-access method">getByText</span><span class="token punctuation">(</span><span class="token string">"Emailが正しくありません。"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span> <span class="token function property-access method">toBeInTheDocument</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre>]]></content>
        <published>2022-08-13T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Shopify App Node を Firebase にデプロイするシステム構成]]></title>
        <id>ja-JP-shopify-app-node-on-firebase</id>
        <link href="https://blog.tomoyukikashiro.me/ja-JP/post/shopify-app-node-on-firebase"/>
        <updated>2022-08-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Shopify App Node を Firebase にのせて動かすためのシステム構成案、紆余曲折をまとめてみました。]]></summary>
        <content type="html"><![CDATA[<h2 id=はじめに><a href=#はじめに aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>はじめに</h2><p>Shopify App Node は、公式に Heroku にデプロイする方法が提供されています。しかし、個人的に Heroku は、費用が高いのと DB や CDN などインフラ、ミドルウェアを追加するたびに様々なサービスを連携させるのが好みではなく、包括的にインフラを構築できる Google Could Platform または Firebase で方法を模索していました。その過程と結論を残しておこうと思います。<h2 id=構成案1-firebase-hosting-and-functions><a href=#構成案1-firebase-hosting-and-functions aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>構成案1： Firebase Hosting and Functions</h2><p>まずは、一番はじめに思いつく素直な構成です。<p><img alt=image src=https://i.gyazo.com/f912264ba56d3aa456edda8776254c0d.png><p>Firebase Hosting で Functions を rewrite してあげて、<code>/auth</code> や <code>/webhooks</code> 、html を配信する構成です。<br>html の配信で Hosting を使わない理由は、Shopify App Node でもページへアクセスした場合に、アプリをインストール済みかどうか判定して、必要であれば OAuth へリダイレクトするロジックを html 配信の前に実行するためです。<h3 id=結論><a href=#結論 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>結論</h3><p>結論として、この構成案ではうまくいきませんでした。<br>Shopify App Node はその仕組上、<a href=https://blog.tomoyukikashiro.me/post/ja/two-http-cookies-shopify-app-node-uses/>2つの HTTP Cookie を使います</a>。しかし、すべての endpoint を束ねている Firebase Hosting は <a href="https://firebase.google.com/docs/hosting/manage-cache?hl=ja#using_cookies">HTTP Cookie を例外を除いて利用できません</a>。よって Shopify App Node は期待通り動きませんでした。<p>ちなみに Firebase Hosting でも使える唯一の例外 Cookie 名である <code>__session</code> を Shopify App Node がセッション管理に使う <code>shopify_app_session</code> の代わりに使う案も考えました。<pre class=language-javascript><code class="language-javascript code-highlight"><span class=code-line><span class="token maybe-class-name">Shopify</span><span class="token punctuation">.</span><span class="token property-access"><span class="token maybe-class-name">Auth</span></span><span class="token punctuation">.</span><span class="token constant">SESSION_COOKIE_NAME</span> <span class="token operator">=</span> <span class="token string">"shopify_app_session"</span><span class="token punctuation">;</span>
</span></code></pre><p>しかし、これでもうまくいきませんでした。 Cookie 生成ロジックを持ってる <a href=https://github.com/Shopify/shopify-node-api>@shopify/shopify-api</a> は Cookie の操作に <a href=https://github.com/pillarjs/cookies>cookies</a> というモジュールを利用しています。このモジュールでは暗号化 cookie を生成する際に、Cookie 名の最後に <code>.sig</code> をつける処理が含まれています。つまり <code>shopify_app_session</code> という Cookie 名をセットしても、 <code>shopify_app_session.sig</code> になってしまい、Firebase Hosting が許可しない Cookie 名で使えませんでした。<h2 id=構成案2auth-だけ-firebase-hosting-を使わない><a href=#構成案2auth-だけ-firebase-hosting-を使わない aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>構成案2：<code>/auth</code> だけ Firebase Hosting を使わない</h2><p>構成案1の問題点である、「Cookie が使えない」という部分に対処した構成です。<br>Shopify App Node が使う Cookie は <code>/auth</code> の endpoint でセットされます。よってこの endpoint のみ Firebase Hosting を通さなければうまくいくはずです。<p><img alt=image src=https://i.gyazo.com/9f7eb5148088f52a01861e9ba152920f.png>)<h3 id=結論-1><a href=#結論-1 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>結論</h3><p>この構成でもうまくいきませんでした。<br>OAuth 認証をする際に、 <code>/auth</code> へリダイレクトする処理ですが、一見すると、 <code>×××.web.app/index.html</code> から <code>us-central1-×××.cloudfunctions.net/auth</code> にリダイレクトでうまくいきそうでしたが、できませんでした。<p>Firebase Hosting で rewrite しているとはいえ、すべての function の実態は <code>us-central1-×××.cloudfunctions.net</code> にあります。<br>つまり、index.html を返している functions から見れば、 <code>us-central1-×××.cloudfunctions.net/index.html</code> へのリクエストを <code>us-central1-×××.cloudfunctions.net/auth</code> にリダイレクトすることになります。<p>詳しく仕様までは追えていませんでしたが、 <strong>同一ドメインのリダイレクトは、たとえ明示的にドメインを指定しても省略される</strong> ようです。<br>つまり、 <code>us-central1-×××.cloudfunctions.net/index.html</code> へのリクエストを <code>us-central1-×××.cloudfunctions.net/auth</code> にリダイレクトする処理を書いても、 <code>/auth</code> （ドメインを除いたパスだけ）へリダイレクトする HTTP レスポンスを返します。<p>そのまま、Firebase Hosting を通ってブラウザにレスポンスが戻るので結果、<code>×××.web.app/index.htm</code> のリクエストで認証するためにリダイレクトすると <code>×××.web.app/auth</code> へリダイレクトするレスポンスが返ってしまい、Firebase Hosting を使っていない <code>/auth</code> へリクエストをリダイレクトさせることができませんでした。<p>よってこの構成案もボツです。<h2 id=構成案3firebase-hosting-の-rewrite-を使わない><a href=#構成案3firebase-hosting-の-rewrite-を使わない aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>構成案3：Firebase Hosting の rewrite を使わない</h2><p>諸悪の根源が Firebase Hosting の rewrite なのでそれを一切つかない構成です。<p><img alt=image src=https://i.gyazo.com/26569d81605e6607c30114f74e94de6f.png><h3 id=結論-2><a href=#結論-2 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>結論</h3><p>成功！動きました。Firebase Hosting で rewrite させる構成より、ローカルも本番環境も少し複雑になりますが、動かくことは問題なさそうです。しかし、せっかく、Firebse Hosting で HTTPS のドメイン（<code>×××.web.app</code>）があるのに使えないのがもったいない気がします。<h2 id=構成案4oauth認証の-endpoint-のみ-cloud-functions-を使う><a href=#構成案4oauth認証の-endpoint-のみ-cloud-functions-を使う aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>構成案4：OAuth認証の endpoint のみ Cloud Functions を使う</h2><p>何かと問題になる <code>/auth</code> の endpoint。<br>Cookie を使うために Firebase Hosting を使えず、他の Firebase Functions からリダイレクトを正しくするために別ドメインで動かす必要があります。なので、それだけ 素の Google Cloud Functions に乗せて動かす構成です。<p><img alt=image src=https://i.gyazo.com/c3536f2fa1147e990833d408ab52f006.png><h3 id=結論-3><a href=#結論-3 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>結論</h3><p>成功！動きました。 <code>構成案4</code> に比べていくらか、構成がシンプルなのと Firebase Hositng のドメインをそのまま利用できるのが良い点です。<p>欠点は、ローカル、本番環境ともに Google Cloud Functions と Firebase Functions を用意する必要があるのでぱっとみわかりにくい点。<br>Google Cloud Functions である <code>/auth</code> のシステムは、認証終わったあとの戻し先として Firebase Functions のドメインを知る必要があり、また、Firebase Functions は、認証する際に <code>/auth</code> である Google Cloud Functions のドメインをしる必要があるので、インフラがお互いに依存している点が気になるところです。<h2 id=まとめ><a href=#まとめ aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>まとめ</h2><ul><li>構成案3：Firebase Hosting の rewrite を使わない<li>構成案4：OAuth認証の endpoint のみ Cloud Functions を使う</ul><p>のどちらがいいかは、好みの問題なので好きな方を使えばいいかと思います！]]></content>
        <published>2022-06-22T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Shopify App Node で使われる2つの HTTP Cookie]]></title>
        <id>ja-JP-two-http-cookies-shopify-app-node-uses</id>
        <link href="https://blog.tomoyukikashiro.me/ja-JP/post/two-http-cookies-shopify-app-node-uses"/>
        <updated>2022-08-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Shopify App Node で使われる「shopify_app_session」と「shopify_top_level_oauth」の2つの Cookie について説明します。]]></summary>
        <content type="html"><![CDATA[<h2 id=背景><a href=#背景 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>背景</h2><p>昨今の 3rd party cookie 規制強化の流れで Shopify App で利用する認証 cookie も影響を受けて、2020年に Shopify Embedded App が受け取る Shopify Admin の認証情報を cookie に依存しない実装に変わりました。<p><a href=https://github.com/Shopify/shopify-app-template-node/pull/493>https://github.com/Shopify/shopify-app-template-node/pull/493</a><p>具体的には、 Shopify Admin に embedded されたアプリケーションは、Shopify App Bridge を経由して、親 frame である Shopify Admin のセッション情報（id や shop の url) を JWT の形式で受け取ります。<h2 id=疑問><a href=#疑問 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>疑問</h2><p>とはいえ、<a href=https://github.com/Shopify/shopify-app-template-node>Shopify App Node</a> を動かしてみるといくつか Cookie を使ってるようです。<br>気になったので、ここで使われてる Cookie が何に利用されるものなのか調査しました。<h2 id=shopify_app_session><a href=#shopify_app_session aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a><code>shopify_app_session</code></h2><p>アプリケーションのセッション情報を Cookie に保存する際の cookie の名前です。<p>Shopify App Node が <a href=https://github.com/Shopify/shopify-node-api>shopify-node-api</a> を利用して OAuth プロセスで取得したアクセストークン等のセッション情報をSessionStorageに保存します。これは、 <code>/auth/callback</code> のエンドポイント内の <a href=https://github.com/Shopify/shopify-app-template-node/blob/a572a919cf26b1e913fe176e6605191c5a8bd024/server/middleware/auth.js#L45-L49>Shopify.Auth.validateAuthCallback</a> で行われるため、この Cookie 名は Shopify App Node を検索してもヒットしません。<p>先程説明した通り、embedded app は 親 frame である Shopify Admin からもらったセッション情報（主に user id や shop の url など アクセストークン以外の情報）をJTW形式でもらいます。<p>JWT の user id, shop url と <code>Shopify_app_session</code> の cookie に紐づくアプリケーションのセッション情報をSessionStorageから取り出し、user id / shop url などが同じである場合、また有効期限内である場合、有効なセッションとして扱います。<h2 id=shopify_top_level_oauth><a href=#shopify_top_level_oauth aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a><code>shopify_top_level_oauth</code></h2><p>先程説明した <code>shopify_app_session</code> の セッション Cookie を保存するためには 1st party cookie にする必要があります。<br>つまり、embedded app のように iframe に埋め込まれるアプリケーションだったとしても、OAuth 認証をする場合はそのリクエストは iframe の外側 で行う必要があります。<p><code>/auth/</code> で OAuth を始める際にそのリクエストが iframe の外側からなのか、それとも内側からなのか判定して、外側の場合にエラーを返すような実装をしたいところですが、HTTP リクエストからそのリクエスト元が <code>iframe の内側なのか</code> を判定することはできません。 Shopify App Node ではそれを Cookie の <code>sameSite</code> 属性をうまく利用して判定しています。<p>Shopify App Node の <a href=https://github.com/Shopify/shopify-app-template-node/blob/a572a919cf26b1e913fe176e6605191c5a8bd024/server/middleware/auth.js>server/middleware/auth.js</a> が該当コードです。<br>以下、その処理の説明になります。<h3 id=auth-へのリクエストが-iframe-の外側からの場合><a href=#auth-へのリクエストが-iframe-の外側からの場合 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a><code>/auth</code> へのリクエストが iframe の外側からの場合</h3><ul><li>STEP1：<code>/auth</code> にリクエスト<ul><li>最初は <code>shopify_top_level_oauth</code> の cookie が存在しないので <code>/auth/top-level</code> にリダイレクト</ul><li>STEP2：<code>/auth/top-level</code><ul><li><code>shopify_top_level_oauth</code> の cookie を <code>samesite=strict</code> で発行<li>また、 JavaScript を返却し browser で実行<ul><li>iframe の 外側なので（<code>window.top === window.self</code> で判定）<code>/auth</code> にリダイレクト</ul></ul><li>STEP3：<code>/auth</code><ul><li><code>/auth/top-level</code> が iframe の外側で、そこから <code>/auth</code> へリダイレクトした場合、<code>/auth</code> で <code>shopify_top_level_oauth</code> の cookie が読めるので、認証処理を開始できる<li>つまり、iframe の外側にいることの確認が取れたことになる</ul></ul><h3 id=auth-へのリクエストが-iframe-の内側からの場合><a href=#auth-へのリクエストが-iframe-の内側からの場合 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a><code>/auth</code> へのリクエストが iframe の内側からの場合</h3><ul><li>STEP1：<code>/auth</code> にリクエスト<ul><li>最初は <code>shopify_top_level_oauth</code> の cookie が存在しないので <code>/auth/top-level</code> にリダイレクト</ul><li>STEP2：<code>/auth/top-level</code><ul><li><code>shopify_top_level_oauth</code> の cookie を <code>samesite=strict</code> で発行<li>また、 JavaScript を返却し browser で実行<ul><li>iframe の 内側なので App Bridge のリダイレクト機能を利用して iframe の親 window で <code>/auth/top-level</code> にリダイレクト<li><code>/auth</code> にリダイレクトしない理由は、iframe の内側からのリクエストに対して <code>samesite=strict</code> で発行した cookie は ブラウザに保存されれないためです</ul></ul><li>STEP3：<code>/auth/top-level</code><ul><li>iframe の 外側からのリクエストでまた同様に <code>shopify_top_level_oauth</code> の cookie を <code>samesite=strict</code> で発行<li>以降は、<code>/auth へのリクエストが iframe の外側からの場合</code> と同じになる</ul></ul><p>以上のように、iframe の 内側か、外側かの判定はブラウザ側でして、その結果の判断は <code>samesite=strict</code> で発行された cookie の有無によって行われている。]]></content>
        <published>2022-06-18T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[chrome85のアップデート情報まとめ]]></title>
        <id>ja-JP-chrome-85-updates</id>
        <link href="https://blog.tomoyukikashiro.me/ja-JP/post/chrome-85-updates"/>
        <updated>2022-08-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[この記事は、Google Chrome85アップデート情報の英語記事を日本語でサクッと解説していきます。公式情報を追いたいけど、英語が苦手で読めてなかったという方でも問題ありません。]]></summary>
        <content type="html"><![CDATA[<h1 id=chrome-85のアップデート情報まとめ><a href=#chrome-85のアップデート情報まとめ aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>chrome 85のアップデート情報まとめ</h1><p>この記事は、<a href=https://developers.google.com/web/updates/2020/08/nic85>Google Chrome85アップデート情報の英語記事</a> と <a href=https://developers.google.com/web/updates/2020/06/devtools>Google Chrome85のdevtoolsのアップデート情報の英語記事</a> を日本語でサクッと解説していきます。<p>公式情報を追いたいけど、英語が苦手で読めてなかったという方でも問題ありません。<br>10分程度で読めるので、ぜひご覧ください！<h2 id=css-content-visibility><a href=#css-content-visibility aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>CSS Content Visibility</h2><pre class=language-css><code class="code-highlight language-css"><span class=code-line><span class="token selector"><span class="token class">.section</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token property">content-visibility</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><p>ページがviewport（画面に表示している範囲）にくるまで対象のレンダリングをして、その分ページの表示スピードのパフォーマンスを上げる新しいプロパティが利用可能になりました。<p><code>flexbox</code> や <code>grid</code> などの複雑なレイアウトアルゴリズムを持つ要素や、それを子に持つ親要素に適用することで効果が期待できます。<blockquote><p>参照：<a href=https://web.dev/content-visibility/>content-visibility: the new CSS property that boosts your rendering performance</a></blockquote><h2 id=property-and-css-variables><a href=#property-and-css-variables aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>@property and CSS variables</h2><p>CSS Variableの定義をJSからだけでなく、CSSからもできるようになりました。<pre class=language-js><code class="language-js code-highlight"><span class=code-line><span class="token constant">CSS</span><span class="token punctuation">.</span><span class="token property-access function method">registerProperty</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token property literal-property">name</span><span class="token operator">:</span> <span class="token string">'--colorPrimary'</span><span class="token punctuation">,</span>
</span><span class=code-line>  <span class="token property literal-property">syntax</span><span class="token operator">:</span> <span class="token string">'&#60color>'</span><span class="token punctuation">,</span>
</span><span class=code-line>  <span class="token property literal-property">initialValue</span><span class="token operator">:</span> <span class="token string">'magenta'</span><span class="token punctuation">,</span>
</span><span class=code-line>  <span class="token property literal-property">inherits</span><span class="token operator">:</span> <span class="token boolean">false</span>
</span><span class=code-line><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre><p>Chrome78からは上記のように、CSS Variableがどんな値で初期値は何で継承する値なのかどうかのような、Variableの定義を宣言できましたが、これと同じことをCSSからもできるようになりました。<pre class=language-css><code class="code-highlight language-css"><span class=code-line><span class="token atrule"><span class="token rule">@property</span> <span class="token variable">--colorPrimary</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token property">syntax</span><span class="token punctuation">:</span> <span class="token string">'&#60color>'</span><span class="token punctuation">;</span>
</span><span class=code-line>  <span class="token property">initial-value</span><span class="token punctuation">:</span> <span class="token color">magenta</span><span class="token punctuation">;</span>
</span><span class=code-line>  <span class="token property">inherits</span><span class="token punctuation">:</span> false<span class="token punctuation">;</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><p>CSSのライブラリで、Theming機能があるものなんかでは利用されそうなです！<blockquote><p>参照：<a href=https://web.dev/at-property/>@property: giving superpowers to CSS variables</a></blockquote><h2 id=get-installed-related-apps><a href=#get-installed-related-apps aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Get installed related apps</h2><pre class=language-js><code class="language-js code-highlight"><span class=code-line><span class="token keyword">const</span> relatedApps <span class="token operator">=</span> <span class="token keyword control-flow">await</span> <span class="token variable dom">navigator</span><span class="token punctuation">.</span><span class="token property-access function method">getInstalledRelatedApps</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line>relatedApps<span class="token punctuation">.</span><span class="token property-access function method">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">app</span><span class="token punctuation">)</span> <span class="token operator arrow">=></span> <span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token class-name console">console</span><span class="token punctuation">.</span><span class="token property-access function method">log</span><span class="token punctuation">(</span>app<span class="token punctuation">.</span><span class="token property-access">id</span><span class="token punctuation">,</span> app<span class="token punctuation">.</span><span class="token property-access">platform</span><span class="token punctuation">,</span> app<span class="token punctuation">.</span><span class="token property-access">url</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre><p>Nativeアプリ側で関連するサイトを定義しておくことで、サイト側ではそのアプリがインストールされているかどうかの判別がつくようになります。<p>今まではNativeアプリのインストールの検知でしたが、PWAやwindowsにおけるアプリのインストール状況のこのAPIで検知可能となっています。<blockquote><p>参照：<a href=https://web.dev/get-installed-related-apps/>Is your app installed? getInstalledRelatedApps() will tell you!</a></blockquote><h2 id=origin-trial-streaming-requests-with-fetch><a href=#origin-trial-streaming-requests-with-fetch aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Origin Trial: Streaming requests with fetch()</h2><pre class=language-js><code class="language-js code-highlight"><span class=code-line><span class="token keyword">const</span> <span class="token punctuation">{</span> readable<span class="token punctuation">,</span> writable <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">TransformStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line>
</span><span class=code-line><span class="token keyword">const</span> responsePromise <span class="token operator">=</span> <span class="token function">fetch</span><span class="token punctuation">(</span>url<span class="token punctuation">,</span> <span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token property literal-property">method</span><span class="token operator">:</span> <span class="token string">'POST'</span><span class="token punctuation">,</span>
</span><span class=code-line>  <span class="token property literal-property">body</span><span class="token operator">:</span> readable<span class="token punctuation">,</span>
</span><span class=code-line><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre><p>fetchメソッドでstreamingでサーバーに送信可能になる機能がorigin trialで開始しています。<br>例えばビデオや音声なんかをディバイスから受信しつつサーバーに送ることなんかが可能です！<p>今までは、一度ビデオや音声をすべて取り込んでからではないと送信できませんでした。<blockquote><p>参照：<a href=https://web.dev/fetch-upload-streaming/>treaming requests with the fetch API</a></blockquote><h2 id=promiseany><a href=#promiseany aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Promise.any</h2><pre class=language-js><code class="language-js code-highlight"><span class=code-line><span class="token keyword control-flow">try</span> <span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token keyword">const</span> first <span class="token operator">=</span> <span class="token keyword control-flow">await</span> <span class="token class-name known-class-name">Promise</span><span class="token punctuation">.</span><span class="token property-access function method">any</span><span class="token punctuation">(</span>arrayOfPromises<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line>  <span class="token class-name console">console</span><span class="token punctuation">.</span><span class="token property-access function method">log</span><span class="token punctuation">(</span>first<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token punctuation">}</span> <span class="token keyword control-flow">catch</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token class-name console">console</span><span class="token punctuation">.</span><span class="token property-access function method">log</span><span class="token punctuation">(</span>error<span class="token punctuation">.</span><span class="token property-access">errors</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><p>Promise.anyを使うことで、引数で渡したPromiseの配列の中で、一番先に <code>fulfiled</code> になった <code>1つ結果</code> のみを取得可能です。<h2 id=stringprototypereplaceall><a href=#stringprototypereplaceall aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>String.prototype.replaceAll</h2><pre class=language-js><code class="language-js code-highlight"><span class=code-line><span class="token keyword">const</span> myName <span class="token operator">=</span> <span class="token string">'My name is Bond, James Bond.'</span>
</span><span class=code-line>    <span class="token punctuation">.</span><span class="token property-access function method">replaceAll</span><span class="token punctuation">(</span><span class="token string">'Bond'</span><span class="token punctuation">,</span> <span class="token string">'Powers'</span><span class="token punctuation">)</span>
</span><span class=code-line>    <span class="token punctuation">.</span><span class="token property-access function method">replace</span><span class="token punctuation">(</span><span class="token string">'James'</span><span class="token punctuation">,</span> <span class="token string">'Austin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token class-name console">console</span><span class="token punctuation">.</span><span class="token property-access function method">log</span><span class="token punctuation">(</span>myName<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token comment">// My name is Powers, Austin Powers.</span>
</span></code></pre><p>文字列に含まれる特定文字 <code>すべて</code> を置換するには、<code>replace(/foo/g, 'bar')</code> のような正規表現とgオプションでおこなっていましたが、上記のような単純なメソッドで可能になっていません！わざわざ正規表現を書く必要はなくなりました！<h2 id=support-avif><a href=#support-avif aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Support AVIF</h2><p>最近safariの13からwebp対応になり話題になりましたが、Chromeではwebpより圧縮率の高い、<a href=https://aomediacodec.github.io/av1-avif/>AVIF</a>フォーマットのサーポートを開始しています。<h1 id=devtools><a href=#devtools aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Devtools</h1><p><a href=https://developers.google.com/web/updates/2020/06/devtools>https://developers.google.com/web/updates/2020/06/devtools</a><br>以降はDevtoolsの更新情報まとめです！<h2 id=style-editing-for-css-in-js-frameworks><a href=#style-editing-for-css-in-js-frameworks aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Style editing for CSS-in-JS frameworks</h2><pre class=language-js><code class="language-js code-highlight"><span class=code-line><span class="token keyword">const</span> sheet <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">CSSStyleSheet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line>sheet<span class="token punctuation">.</span><span class="token property-access function method">insertRule</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string template-punctuation">`</span><span class="token string">h1 {
</span></span></span><span class=code-line><span class="token template-string"><span class="token string">  background: pink;
</span></span></span><span class=code-line><span class="token template-string"><span class="token string">  text-transform: uppercase;
</span></span></span><span class=code-line><span class="token template-string"><span class="token string">}</span><span class="token string template-punctuation">`</span></span><span class="token punctuation">)</span>
</span><span class=code-line><span class="token variable dom">document</span><span class="token punctuation">.</span><span class="token property-access">adoptedStyleSheets</span> <span class="token operator">=</span> <span class="token punctuation">[</span>sheet<span class="token punctuation">]</span><span class="token punctuation">;</span>
</span></code></pre><p>CSS-in-JSフレームワークでJSで定義したスタイルを上記のようにページに反映した場合、適用されたスタイルをdevtoolsでは編集できませんでしたが、本バージョンからは通常のCSS同様編集できるようになりました！<h2 id=lighthouse-6-in-the-lighthouse-panel><a href=#lighthouse-6-in-the-lighthouse-panel aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Lighthouse 6 in the Lighthouse panel</h2><p>Lighthouse タブで動くLighthouseがv6になりました。<br>v6ではCore Web Vitalsの計測もはいっています。<p>Lighthouse v6の詳しい内容は、<a href=https://web.dev/lighthouse-whats-new-6.0/>What’s New in Lighthouse 6.0</a>を参照ください！<h2 id=support-for-new-javascript-features><a href=#support-for-new-javascript-features aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Support for new JavaScript features</h2><p>ConsoleタブやSourceタブでJSを書いた際に、Optional chainingの自動補完、private field、Nullish coalescingのシンタックスハイライトが追加になっています。<h2 id=new-app-shortcut-warnings-in-the-manifest-pane><a href=#new-app-shortcut-warnings-in-the-manifest-pane aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>New app shortcut warnings in the Manifest pane</h2><p>ApplicationタブのManifest欄で、App Shortcutのアイコンサイズ不足によるエラーを表示するようになっています！]]></content>
        <published>2020-08-29T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[chrome84のアップデート情報まとめ]]></title>
        <id>ja-JP-chrome-84-updtes</id>
        <link href="https://blog.tomoyukikashiro.me/ja-JP/post/chrome-84-updtes"/>
        <updated>2022-08-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[この記事は、Google Chrome84アップデート情報の英語記事を日本語でサクッと解説していきます。公式情報を追いたいけど、英語が苦手で読めてなかったという方でも問題ありません。]]></summary>
        <content type="html"><![CDATA[<h1 id=chrome-84のアップデート情報まとめ><a href=#chrome-84のアップデート情報まとめ aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>chrome 84のアップデート情報まとめ</h1><p>この記事は、<a href=https://developers.google.com/web/updates/2020/07/nic84>Google Chrome84アップデート情報の英語記事</a>を日本語でサクッと解説していきます。<p>公式情報を追いたいけど、英語が苦手で読めてなかったという方でも問題ありません。<br>10分程度で読めるので、ぜひご覧ください！<h2 id=app-icon-shortcuts><a href=#app-icon-shortcuts aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>App Icon Shortcuts</h2><p>Androidのnativeアプリのアイコンを長押すると、表示するショートカットメニューがPWAでもできるようになりました。<p><a href=https://gyazo.com/4bdfd0d4bd666e05a555c09e625f9b5f><img alt="Image from Gyazo"src=https://i.gyazo.com/4bdfd0d4bd666e05a555c09e625f9b5f.png></a><p>設定方法はmanifest.jsonに記述するだけと、とてもシンプルです。<pre class=language-json><code class="code-highlight language-json"><span class=code-line><span class="token property">"shortcuts"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
</span><span class=code-line>  <span class="token punctuation">{</span>
</span><span class=code-line>    <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"Open Play Later"</span><span class="token punctuation">,</span>
</span><span class=code-line>    <span class="token property">"short_name"</span><span class="token operator">:</span> <span class="token string">"Play Later"</span><span class="token punctuation">,</span>
</span><span class=code-line>    <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"View the list you saved for later"</span><span class="token punctuation">,</span>
</span><span class=code-line>    <span class="token property">"url"</span><span class="token operator">:</span> <span class="token string">"/play-later"</span><span class="token punctuation">,</span>
</span><span class=code-line>    <span class="token property">"icons"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
</span><span class=code-line>      <span class="token punctuation">{</span> <span class="token property">"src"</span><span class="token operator">:</span> <span class="token string">"//play-later.png"</span><span class="token punctuation">,</span> <span class="token property">"sizes"</span><span class="token operator">:</span> <span class="token string">"192x192"</span> <span class="token punctuation">}</span>
</span><span class=code-line>    <span class="token punctuation">]</span>
</span><span class=code-line>  <span class="token punctuation">}</span><span class="token punctuation">,</span>
</span><span class=code-line><span class="token punctuation">]</span>
</span></code></pre><p>ただし、私のAndroid Chrome（84.0.4147.89.）ではまだ動きませんでした。確認するには、Canary版を利用してみてください。<br>詳しい解説記事（英語）は以下にあります。<p><a href=https://web.dev/app-shortcuts/>https://web.dev/app-shortcuts/</a><h2 id=web-animations-api><a href=#web-animations-api aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Web Animations API</h2><p>Web Animations APIにもいくつか改善が施されています。<ul><li>いくつかのAPI（animation.ready / animation.finished）がPromiseオブジェクトを返すように<li>mousemoveなどeventによるアニメーションの置換処理のパフォーマンス改善<li>composite modeのサーポート</ul><p>などがあります。<br>詳細はこちら別記事にまとまってるようなので、<a href=https://web.dev/web-animations/>https://web.dev/web-animations/</a> をご確認ください。<h2 id=content-indexing-api><a href=#content-indexing-api aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Content Indexing API</h2><p>Content Indexing APIがOrigin Trialを終えました。<br>記事などのコンテツをオフラインで読めるようにキャッシュし、その後、ユーザーがオフラインになった時、「この記事ダウンロード済みなので読めますよ」とChromeが提示してくれます。<br>コンテンツをキャッシュすると、すべて提示されるわけではなく、自分で「提示リスト」に登録する必要があります。<p>それが、Content Indexing APIです。<br>登録には以下のようにします。<pre class=language-javascript><code class="language-javascript code-highlight"><span class=code-line><span class="token keyword">const</span> registration <span class="token operator">=</span> <span class="token keyword control-flow">await</span> <span class="token dom variable">navigator</span><span class="token punctuation">.</span><span class="token property-access">serviceWorker</span><span class="token punctuation">.</span><span class="token property-access">ready</span><span class="token punctuation">;</span>
</span><span class=code-line><span class="token keyword control-flow">await</span> registration<span class="token punctuation">.</span><span class="token property-access">index</span><span class="token punctuation">.</span><span class="token property-access function method">add</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token property literal-property">id</span><span class="token operator">:</span> <span class="token string">'article-123'</span><span class="token punctuation">,</span>
</span><span class=code-line>  <span class="token property literal-property">url</span><span class="token operator">:</span> <span class="token string">'/articles/123'</span><span class="token punctuation">,</span>
</span><span class=code-line>  <span class="token property literal-property">launchUrl</span><span class="token operator">:</span> <span class="token string">'/articles/123'</span><span class="token punctuation">,</span>
</span><span class=code-line>  <span class="token property literal-property">title</span><span class="token operator">:</span> <span class="token string">'Article title'</span><span class="token punctuation">,</span>
</span><span class=code-line>  <span class="token property literal-property">description</span><span class="token operator">:</span> <span class="token string">'Amazing article about things!'</span><span class="token punctuation">,</span>
</span><span class=code-line>  <span class="token property literal-property">icons</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>
</span><span class=code-line>    <span class="token property literal-property">src</span><span class="token operator">:</span> <span class="token string">'/img/article-123.png'</span><span class="token punctuation">,</span>
</span><span class=code-line>    <span class="token property literal-property">sizes</span><span class="token operator">:</span> <span class="token string">'64x64'</span><span class="token punctuation">,</span>
</span><span class=code-line>    <span class="token property literal-property">type</span><span class="token operator">:</span> <span class="token string">'image/png'</span><span class="token punctuation">,</span>
</span><span class=code-line>  <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
</span><span class=code-line><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre><p>提示する場所が、Chromeのダウンロードメニューバー内と、とても分かりにくい場所なので、あまり使うことなさそうですが、提示する場所は随時拡大予定みないなので、記事系コンテツは試してみてもいいかもしれません。<p><img alt=image src=https://i.gyazo.com/a05d185ac8a0d6d0a0f08ef913f9273f.png><p>下記で試すことができます。<br><a href=https://contentindex.dev/>https://contentindex.dev/</a><h2 id=wake-lock-api><a href=#wake-lock-api aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Wake Lock API</h2><p>Wake Lock APIもOrigin Trialを終えました。<br>レシピサイトでレシピを長い時間、操作せずに見ていると、画面がOFFになってしまうことがあります。<br>ユーザが一定時間操作してないので、設定によって自動で画面OFFになるからです。<p>これを止めるのが、Wake Lock APIです。<pre class=language-javascript><code class="language-javascript code-highlight"><span class=code-line><span class="token comment">// Request the wake lock</span>
</span><span class=code-line><span class="token keyword">const</span> wl <span class="token operator">=</span> <span class="token keyword control-flow">await</span> <span class="token dom variable">navigator</span><span class="token punctuation">.</span><span class="token property-access">wakeLock</span><span class="token punctuation">.</span><span class="token property-access function method">request</span><span class="token punctuation">(</span><span class="token string">'screen'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span><span class=code-line>
</span><span class=code-line><span class="token comment">// Release the wake lock</span>
</span><span class=code-line>wl<span class="token punctuation">.</span><span class="token property-access function method">release</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></code></pre><p>この機能をユーザーに提示することで、300%購入が増加したというケーススタディも公開されているので気になる人はぜひチェックしてください。<br><a href=https://web.dev/betty-crocker/>https://web.dev/betty-crocker/</a><h2 id=new-origin-trials><a href=#new-origin-trials aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>New Origin Trials</h2><p>いくつかのAPIはOrigin Trialで利用可能になったので紹介します。<h3 id=idle-detection-api><a href=#idle-detection-api aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Idle Detection API</h3><p>ユーザーが端末から離れた状態（Idle）を検知するAPIです。 あくまで、<code>端末から離れた可能性と戻ってきた可能性</code> を検知する機能です。<br>SNSやチャットサイトでは、<code>Idleからactiveになった時</code> に通知を再開したり、受付アプリでは <code>Idleになった時</code> 画面をhomeに戻したりできます。<h3 id=web-assembly-simdシムディ><a href=#web-assembly-simdシムディ aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Web Assembly SIMD（シムディ）</h3><p>並列処理を行うための設計様式のSIMDをWeb Assemblyでもサポートしたとのこと。<br>これにより、特にクラフィックス処理の向上が期待できます。<p>くわしくは、V8の記事を確認ください。<br><a href=https://v8.dev/features/simd>https://v8.dev/features/simd</a><h2 id=samesite-cookiesの再開><a href=#samesite-cookiesの再開 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>SameSite cookiesの再開</h2><p>クロスサイトな通知でCookieを利用する場合に <code>SameSite</code> の初期値が <code>Lax</code> に変わる段階的変更は、4月コロナウイルスの影響で一時停止していましたが、chrome84から再開します。一斉に適用するわけではなく、chrome84から段階的にこの設定が有効になるとのことです。<p>詳しくは、私のブログ、Youtubeにもまとめていますので、気になる人はぜひチェックしてみてください。<p><a href=https://blog.tomoyukikashiro.me/post/ja/what-is-samesite-cookie/>https://blog.tomoyukikashiro.me/post/ja/what-is-samesite-cookie/</a><br><a href="https://www.youtube.com/watch?v=FHh9cAfiRJA">https://www.youtube.com/watch?v=FHh9cAfiRJA</a><h2 id=abusive-permission-requests--notification><a href=#abusive-permission-requests--notification aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Abusive permission requests / notification</h2><p>サイトにアクセスしたらすぐに、<code>通知の許可</code> 等を取ろうとするサイトでは、今まで表示していた通知許可ダイアログがより、小さく、控えめなUIに変更になります。<br>その許可が必要なコンテキストや説明も無いままいきなりパーミッションを取ろうとする行為は、UX的にもよくないので、これを抑制する機能になります。<p>Chrome 84.0.4147.89 ではまだ有効になってませんでしたが、準備適用されると思います。<br>現在、<code>通知の許可</code> を求めるようなコードがあり、<code>右上の通知の許可のOKボタンをクリックしてください</code>的なガイドを入れているサイトは修正が必要になると思います。<br>どのようなUIに変更になるかは、chromiumのブログを参照ください。<p><a href=https://blog.chromium.org/2020/05/protecting-chrome-users-from-abusive.html>https://blog.chromium.org/2020/05/protecting-chrome-users-from-abusive.html</a><h1 id=devtools><a href=#devtools aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Devtools</h1><p><a href=https://developers.google.com/web/updates/2020/05/devtools>https://developers.google.com/web/updates/2020/05/devtools</a><br>以降はDevtoolsの更新情報まとめです！<h2 id=fix-site-issues-with-the-new-issues-tab><a href=#fix-site-issues-with-the-new-issues-tab aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Fix site issues with the new Issues tab</h2><p>SameSite Cookie対応など互換性がないブラウザの変更によりサイトで利用するリソースに問題がある場合に、今まではconsoleのwarningsレベルで表示していました。<br>しかし、アプリケーション自身のログと混在してしまいconsoleが見にくくなる問題がありました。<p><a href=https://gyazo.com/fcb576a96a8f4d0f63c07ce3020fa6c3><img alt="Image from Gyazo"src=https://i.gyazo.com/fcb576a96a8f4d0f63c07ce3020fa6c3.png></a><p>Chrome v84からは、<code>Issues</code>タブにまとめて表示されます。<p><a href=https://gyazo.com/05d9222435e4191d9ea19a2ce1dc1c67><img alt="Image from Gyazo"src=https://i.gyazo.com/05d9222435e4191d9ea19a2ce1dc1c67.png></a><h2 id=view-accessibility-information-in-the-inspect-mode-tooltip><a href=#view-accessibility-information-in-the-inspect-mode-tooltip aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>View accessibility information in the Inspect Mode tooltip</h2><p>inspect mode tooltipsに アクセシビリティの <code>name</code> , <code>role</code> , <code>keyboard-focusable</code> 情報が表示されるようになりました。<p><a href=https://gyazo.com/cef1cd8ed3a015db43d4caa918cc235a><img alt="Image from Gyazo"src=https://i.gyazo.com/cef1cd8ed3a015db43d4caa918cc235a.png></a><h2 id=performance-panel-updates><a href=#performance-panel-updates aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Performance panel updates</h2><ul><li>パフォーマンスタブのfooterにtotal blocking timeが表示するようになった<li>パフォーマンスタブのexperienceセクションにlayout shift情報がでるようになりました</ul><p><a href=https://gyazo.com/2a01a03085da67db2e106a628feed91e><img alt="Image from Gyazo"src=https://i.gyazo.com/2a01a03085da67db2e106a628feed91e.png></a><h2 id=more-accurate-promise-terminology-in-the-console><a href=#more-accurate-promise-terminology-in-the-console aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>More accurate promise terminology in the Console</h2><p>consoleにでるpromiseオブジェクトのstatusが仕様に沿った名前になりました。<p>今までは、Promiseの処理が成功した時、consoleに <code>PromiseStatus</code> が <code>resolved</code> と表示していました。<br>しかし、Promiseの仕様上、statusは、<code>fultilled, reject, settled</code> であり、<code>resolved</code> というstatusはありません。<p>chrome84からは仕様に沿うようにstatusの値が表示するようになりました。<p><a href=https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise</a><h2 id=styles-pane-updates><a href=#styles-pane-updates aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Styles pane updates</h2><ul><li>cssのrevertをautocompleteするようになりました<li>background-imageをプレビューするようになりました<li>CSS Colors Level 4 の仕様から利用可能になった、<code>rgb(0 0 0)</code> のような今までのカンマ区切りではなく、スペース区切りのシンタックスでcolor pickerが表示するようになりました。</ul><h2 id=deprecation-of-the-properties-pane-in-the-elements-panel><a href=#deprecation-of-the-properties-pane-in-the-elements-panel aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Deprecation of the Properties pane in the Elements panel</h2><p>element > propertiesは使えなくなり、代わりに<code>console.dir()</code> を使ってください！<h2 id=app-shortcuts-support-in-the-manifest-pane><a href=#app-shortcuts-support-in-the-manifest-pane aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>App shortcuts support in the Manifest pane</h2><p>App shortcutsの情報がApplicationのmanifestセクションにに表示されるようになりました。<p>“<a href=https://gyazo.com/d9e3bda609da9db97ac1d97c79550b6e><img alt="Image from Gyazo"src=https://i.gyazo.com/d9e3bda609da9db97ac1d97c79550b6e.png></a>]]></content>
        <published>2020-07-25T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[CSS MdiaQueryのmin-widthとmax-widthどちらを使う？]]></title>
        <id>ja-JP-media-query-min-max</id>
        <link href="https://blog.tomoyukikashiro.me/ja-JP/post/media-query-min-max"/>
        <updated>2022-08-03T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[レスポンシブデザインでサイトを作る際に、CSS MediaQueryの min-width / max-width を使いますが、どっちを使っていくべきか悩んでる人も多いのかと思います。この記事では、どっちを使っていくべきか解説していきます。]]></summary>
        <content type="html"><![CDATA[<h2 id=はじめに><a aria-hidden=true href=#はじめに tabindex=-1><span class="icon icon-link"></span></a>はじめに</h2><p>レスポンシブデザインでサイトを作る際に、CSS MediaQueryの min-width / max-width を使いますが、どっちを使っていくべきか悩んでる人も多いのかと思います。<p>この記事では、どっちを使っていくべきか解説していきます。<pre class=language-css><code class="code-highlight language-css"><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">max-width</span><span class="token punctuation">:</span> ◯◯px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>  // 画面サイズが◯◯px以下に適用
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> ◯◯px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>  // 画面サイズが◯◯px以上に適用
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><h2 id=結論><a aria-hidden=true href=#結論 tabindex=-1><span class="icon icon-link"></span></a>結論</h2><p>基本的に、<code>min-width</code> で書いた方が良いです。<br>そのように書くことで、CSSをシンプルに保つことができます。<pre class=language-scss><code class="language-scss code-highlight"><span class=code-line><span class="token comment">// sample.scss</span>
</span><span class=code-line><span class="token selector">.awesome-container </span><span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token property">xxx</span><span class="token punctuation">:</span> xxxx<span class="token punctuation">;</span>
</span><span class=code-line>  <span class="token property">xxx</span><span class="token punctuation">:</span> xxxx<span class="token punctuation">;</span>
</span><span class=code-line>
</span><span class=code-line>  <span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> 100px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>    <span class="token comment">// 画面サイズが100px以上に適用</span>
</span><span class=code-line>  <span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line>  <span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> 300px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>    <span class="token comment">// 画面サイズが300px以上に適用</span>
</span><span class=code-line>  <span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line>  <span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> 500px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>    <span class="token comment">// 画面サイズが500px以上に適用</span>
</span><span class=code-line>  <span class="token punctuation">}</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><h2 id=理由1cssは画面サイズが大きくなるに連れて記述量が増える><a aria-hidden=true href=#理由1cssは画面サイズが大きくなるに連れて記述量が増える tabindex=-1><span class="icon icon-link"></span></a>理由1：CSSは画面サイズが大きくなるに連れて、記述量が増える</h2><p>一般的に、画面サイズの小さいモバイル画面では、要素は上から下へ積み重なっていくようにデザインされて、画面サイズが大きくなるにつれて要素を横並びにしてデザインされることが多いです。<table><thead><tr><th>mobile<th>tablet<th>desktop<tbody><tr><td><img alt=image.png src=https://i.gyazo.com/7e50b2a4ea5f3ef55de66f6af68ae9ef.png><td><img alt=image.png src=https://i.gyazo.com/1147b1455faf01355487447923d397b2.png><td><img alt=image.png src=https://i.gyazo.com/a5088c47cacd4bf9d872c5b768219c68.png></table><p>そして、HTMLで記述された要素は、デフォルトで、<code>左上から下</code> に積み重なっていきます。<p><img alt=image.png src=https://i.gyazo.com/42f0c65aa3b9bfa22cca2c17d02a5e10.png><p>この並びを <code>横</code> にしようとするときCSSの <code>position, float ,display</code> などでスタイルを調整していきます。<br>CSSのプロパティを、装飾目的、レイアウト目的の2つに分類したとすると、<ul><li>装飾目的：color / font-size / font-familly / border<li>レイアウト目的：position / width / height / display</ul><p><strong>レイアウト目的のスタイルは、画面サイズの小さいモバイルだと、不要なケースが多く（縦に並べるだけならCSS不要）、画面サイズが大きくなるにつれて、横並びにするため、必要になってくきます。</strong><p><strong>よって、画面サイズに応じて記述するCSSが増えていくのです。</strong><h2 id=理由2cssはスタイルのキャンセルが手間><a aria-hidden=true href=#理由2cssはスタイルのキャンセルが手間 tabindex=-1><span class="icon icon-link"></span></a>理由2：CSSはスタイルのキャンセルが手間</h2><p>CSSにはスタイルをキャンセルさせる方法がなく、キャンセルしたければ、初期値で上書きする必要があります。<p>前述したように、画面サイズに応じてレイアウト目的のスタイルが増えていくので、先に画面サイズが大きいスタイルを記述すると、レイアウト目的スタイルが不要な小さい画面サイズのスタイルを記述するときに、都度キャンセルする必要がでてきます。<pre class=language-scss><code class="language-scss code-highlight"><span class=code-line><span class="token selector">.awesome-panel </span><span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token comment">// 画面サイズが401px以上はabsolute</span>
</span><span class=code-line>  <span class="token property">position</span><span class="token punctuation">:</span> <span class="token property">absolute</span><span class="token punctuation">:</span>
</span><span class=code-line>
</span><span class=code-line>  <span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">max-width</span><span class="token punctuation">:</span> 400px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>    <span class="token comment">// 画面サイズが400px以下ならpositionの初期値（static）でpositionをキャンセルする</span>
</span><span class=code-line>    <span class="token property">position</span><span class="token punctuation">:</span> static<span class="token punctuation">;</span>
</span><span class=code-line>  <span class="token punctuation">}</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><p>これを、画面サイズが小さいスタイルから記述すると、キャンセルが不要になります。<pre class=language-scss><code class="language-scss code-highlight"><span class=code-line><span class="token selector">.awesome-panel </span><span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token comment">// 画面サイズが400px未満</span>
</span><span class=code-line>  <span class="token comment">// position: static: ←初期値なので記述不要</span>
</span><span class=code-line>
</span><span class=code-line>  <span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> 400px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>    <span class="token comment">// 画面サイズが400px以上ならabsolute</span>
</span><span class=code-line>    <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span>
</span><span class=code-line>  <span class="token punctuation">}</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><h2 id=まとめ><a aria-hidden=true href=#まとめ tabindex=-1><span class="icon icon-link"></span></a>まとめ</h2><ul><li>CSSは画面サイズが大きくなるに連れて記述量が増える<li>CSSはスタイルのキャンセルが手間である</ul><p>という条件から、<code>min-width</code> を利用して小さい → 大きい順にCSSを書くことで、<strong>CSSをシンプルにでき、結果CSSのファイルサイズが小さくなり、メンテナンスしやすいスタイルを書くことができるようになります。</strong><p>また、Webサイトのデザイン・開発は <code>モバイルファースト（モバイル優先）</code> で考えることが当たり前になってきましたが、この書き方はそのポリシーを反映した形になってて、マークアップもモバイルから作ることになるので良いという側面もあります。<pre class=language-scss><code class="language-scss code-highlight"><span class=code-line><span class="token comment">// sample.scss</span>
</span><span class=code-line><span class="token selector">.awesome-container </span><span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token property">xxx</span><span class="token punctuation">:</span> xxxx<span class="token punctuation">;</span>
</span><span class=code-line>  <span class="token property">xxx</span><span class="token punctuation">:</span> xxxx<span class="token punctuation">;</span>
</span><span class=code-line>
</span><span class=code-line>  <span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> 100px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>    <span class="token comment">// 画面サイズが100px以上に適用</span>
</span><span class=code-line>  <span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line>  <span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> 300px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>    <span class="token comment">// 画面サイズが300px以上に適用</span>
</span><span class=code-line>  <span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line>  <span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> 500px<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>    <span class="token comment">// 画面サイズが500px以上に適用</span>
</span><span class=code-line>  <span class="token punctuation">}</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><h2 id=さいごに><a aria-hidden=true href=#さいごに tabindex=-1><span class="icon icon-link"></span></a>さいごに</h2><p>もしこれを読んでもまだ、 <code>max-widthベースの方がいい</code> と感じる人はぜひ、1つのページを <code>min-widthベース</code>と<code>max-width</code> ベースの2通りで書いてみてください！<br>私も <code>どっちでもいいじゃん</code> と思う派だったが、やってみるとmin-widthベースの方が圧倒的に書きやすく驚きました！]]></content>
        <published>2020-03-08T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[CookieのSameSite Attributeとは？]]></title>
        <id>ja-JP-what-is-samesite-cookie</id>
        <link href="https://blog.tomoyukikashiro.me/ja-JP/post/what-is-samesite-cookie"/>
        <updated>2022-08-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[2020年2月のGoogle Chrome v80からCookieのSameSiteの初期値がLaxになります。ドメインをまたいで通信しCookieを利用しているサービスは影響あるかもしれません。SameSiteとはなんなのか、デモを通して説明していきます。]]></summary>
        <content type="html"><![CDATA[<p>Cookie に SameSiteという新しい属性が追加されて、いくつかのブラウザではその初期値が変わる予定です。<p>Google Chrome ではその変更が2020年2月を予定しています。<br>複数のドメインの間で通信をし、Cookieを利用するサービスは影響あるかもしれません。<p>ここでは、 SameSite の概要と影響をさくっと確認していきます。<h2 id=samesite-cookies-とは><a href=#samesite-cookies-とは aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>SameSite Cookies とは？</h2><p>SameSite とは、 Cookie に追加される新しい属性です。<br>Cookie を発行する際は、 key=value と合わせて、属性として Cookie の振る舞いを制御するオプションを設定できます。<br>例えば、<ul><li>Expires : Cookieの有効期限<li>Secure : https の場合のみ利用を制限するかどうかのフラグ<li>HttpOnly : サーバサイドでの利用に制限するかどうかのフラグ</ul><p>などです。<p>SameSite は Cookie がドメインをまたいで利用されるときの挙動を制御する新しいオプションになります。<br>SameSite=Strict, SameSite=Lax, SameSite=None の3つの値から選択できます。<br>詳しい内容は後述します。<h2 id=samesite-cookie-が必要とされる理由><a href=#samesite-cookie-が必要とされる理由 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>SameSite Cookie が必要とされる理由</h2><p>主な理由は、 CSRF（クロスサイトリクエストフォージェリー）という攻撃を防ぐことにあります。<p>例えば、SNSなどでコメントを投稿する機能を例に考えます。<br>コメントを投稿するのに必要な仕様は以下だとします。<ul><li>method : post<li>URL : example.com/comments<li>parameter : body (コメント内容)<li>条件 : ログイン必須（cookieを使って認証管理）<li>方法 : <code>&#60form></code> タグを利用して送信</ul><p>HTMLはこんな感じ。<pre class=language-html><code class="language-html code-highlight"><span class=code-line><span class="token comment">&#60!-- example.com でのコメント投稿機能 --></span>
</span><span class=code-line><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span> <span class="token attr-name">method</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>POST<span class="token punctuation">"</span></span> <span class="token attr-name">action</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://example.com/comments<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
</span><span class=code-line>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>textarea</span> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>コメントを入力<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>body<span class="token punctuation">"</span></span> <span class="token attr-name">rows</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>5<span class="token punctuation">"</span></span> <span class="token attr-name">cols</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>33<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
</span><span class=code-line>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">></span></span>コメント送信<span class="token tag"><span class="token tag"><span class="token punctuation">&#60/</span>button</span><span class="token punctuation">></span></span>
</span><span class=code-line><span class="token tag"><span class="token tag"><span class="token punctuation">&#60/</span>form</span><span class="token punctuation">></span></span>
</span></code></pre><p>もし、アクセスしたユーザーがログイン済みであれば、コメント投稿は成功します。<br>しかし、この実装のままだと、関係ないサービスからでもコメント投稿が成功してしまいます。<br>例えば、<pre class=language-html><code class="language-html code-highlight"><span class=code-line><span class="token comment">&#60!-- example.net （.netなので無関係のサイト）からの、example.com のコメント投稿機能を悪用したいたずら --></span>
</span><span class=code-line><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token css language-css value"><span class="token property">display</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span> <span class="token attr-name">method</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>POST<span class="token punctuation">"</span></span> <span class="token attr-name">action</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://example.com/comments<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
</span><span class=code-line>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>textarea</span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>だれかの悪口。だれかの悪口。だれかの悪口。だれかの悪口。だれかの悪口。だれかの悪口。だれかの悪口。<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
</span><span class=code-line>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">></span></span>コメント送信<span class="token tag"><span class="token tag"><span class="token punctuation">&#60/</span>button</span><span class="token punctuation">></span></span>
</span><span class=code-line><span class="token tag"><span class="token tag"><span class="token punctuation">&#60/</span>form</span><span class="token punctuation">></span></span>
</span></code></pre><p>このような実装で、ユーザーの意思とは関係なく、このformをsubmitすることで、そのログインユーザーのコメントとして投稿されてしまいます。<br>これがクロスサイトリクエストフォージェリーという攻撃です。<p>tokenを使ってリクエストが example.com からであるかどうかを確認する方法でこの攻撃を防ぐのが、よく見る対応です。<br>この攻撃は、別のサイトからの意図しないリクエストであっても cookie 込みで送信されるという cookie の仕様を利用（悪用）した方法とも言えます。<p>SameSite 属性を利用することで、 <code>関係ないサイト => example.com</code> へのリクエスト時に、cookie 込みで送信するかどうかを example.com 側で制御できるようになり、結果としてクロスサイトリクエストフォージェリー対策になります。<h2 id=samesite-の確認方法><a href=#samesite-の確認方法 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>SameSite の確認方法</h2><p>Chrome DevToolsで確認可能です。<br>方法は2つあります。<h3 id=ネットワークタブ><a href=#ネットワークタブ aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>ネットワークタブ</h3><p>Cookieが付与されているドメインのリクエストをネットワークタブで見つけ、詳細内の、 <code>Cookiesタブ</code> で確認可能です。<h3 id=アプリケーションタブ><a href=#アプリケーションタブ aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>アプリケーションタブ</h3><p>アプリケーションタブの <code>Storage</code> > <code>Cookies</code> でドメイン毎に確認可能です。<h2 id=デモを使って確認><a href=#デモを使って確認 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>デモを使って確認</h2><p>さっそく、 SameSite を指定した Cookie がどのようになるのかデモとともにみていきます。<br>ここでは、サイトA（背景色が白）とサイトB（背景色がグレー）の２つのサイトで、3つのリクエストを例に見ていきます<ul><li>サイトAからサイトBへの画面遷移<li>サイトAでiframeを使って、サイトBを表示する際のリクエスト<li>サイトAからサイトBへのXHR</ul><p>サイトBには、 <code>test=test</code> という Cookieが付与されています。<br>サイトBを表示（リクエスト）する際、 <code>test=test</code> のCookieが読み取れれば画面に表示し、読み取れなければ、 <code>test=</code> と表示します。<p>Cookieを設定する際、 <code>SameSite</code> のオプションを変えて、上記3つのリクエストでCookieの読み取りにどんな違いがでるか見ていきます。<h2 id=デモ結果><a href=#デモ結果 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>デモ結果</h2><p>サイトBでCookieの中身を読み取れるか？<table><thead><tr><th>sameSite<th>ページ遷移<th>iframe<th>XHR<tbody><tr><td>strict<td>❌<td>❌<td>❌<tr><td>Lax<td>⭕<td>❌<td>❌<tr><td>None<td>⭕<td>⭕<td>⭕</table><p><a href=https://samesite-cookie.web.app/>https://samesite-cookie.web.app/</a><h2 id=samesiteの利用パターン><a href=#samesiteの利用パターン aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>SameSiteの利用パターン</h2><p>認証管理に例して考えるなら、、、<h3 id=cookieで認証管理しており別ドメインからリクエストを行わないサービス><a href=#cookieで認証管理しており別ドメインからリクエストを行わないサービス aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Cookieで認証管理しており、別ドメインからリクエストを行わないサービス</h3><p>SameSiteを利用することで、クロスサイトリクエストフォージェリーの攻撃を防ぐことができるので、可能な限り、 <code>SameSite=Strict</code> や <code>SameSite=Lax</code> の利用をしていきたいとこです。<h3 id=cookieで認証管理しており別ドメインからリクエストを行うサービス><a href=#cookieで認証管理しており別ドメインからリクエストを行うサービス aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Cookieで認証管理しており、別ドメインからリクエストを行うサービス</h3><p><code>SameSite=Strict</code> や <code>SameSite=Lax</code> を利用すると別ドメインからのリクエストでは、ログイン済みでも、Cookieが付与されて送信されないため、未ログインとして扱われてしまします。<p>また、Chrome, Firefox, Edgeでは SameSite が未指定の場合 <code>SameSite=Lax</code> として扱うことを検討しており、 Chrome version 80で 未指定の場合、 <code>SameSite=Lax</code> として扱い変更がリリースされる予定です。<p>よって、何も対応してないと、2020年2月の Chrome version 80 のリリースのタイミングでこのケースのサービスでは Chrome で <code>ログインできない</code> 不具合が発生します。<br>今まで同じ挙動にするためには、 <code>SameSite=None</code> と <code>Secure</code> のオプションを Cookie に設定する必要があります。<h3 id=忘れがちなパターンの-chrome-extension><a href=#忘れがちなパターンの-chrome-extension aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>忘れがちなパターンの Chrome extension</h3><p>別ドメインでリクエストが発生する忘れがちなパターンに Chrome extension があります。<br>もし Chrome extension を開発している場合は、 2020年2月の Chrome version 80 のリリースのタイミングでトラブルにならないように確認しておきましょう。<h2 id=samesite未指定の場合samesitelaxとして扱われることの確認方法><a href=#samesite未指定の場合samesitelaxとして扱われることの確認方法 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>SameSite未指定の場合、SameSite=Laxとして扱われることの確認方法</h2><p><a href="https://youtu.be/QSKky-bkTQ8?t=324">https://youtu.be/QSKky-bkTQ8?t=324</a>]]></content>
        <published>2020-01-15T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[タブレットのhoverを考え直したい]]></title>
        <id>ja-JP-consider-hover-effect-for-tablet</id>
        <link href="https://blog.tomoyukikashiro.me/ja-JP/post/consider-hover-effect-for-tablet"/>
        <updated>2022-08-13T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[hoverのアクションを利用してUIを実装しているサイトを目にするがタブレットでうまく動かないことが多々あるのでどんなことに気をつけるのか整理してみました。]]></summary>
        <content type="html"><![CDATA[<h2 id=きっかけ><a href=#きっかけ aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>きっかけ</h2><p>最近、IE/Edge確認のためSurface goを買って使ってるんですが、ナビゲーションとかでうまく動かないサイトをたまに見かけます。<br>↓は、bootstrapのhoverを利用したドロップダウンメニューライブラリ<a href=https://kybarg.github.io/bootstrap-dropdown-hover/>bootstrap-dropdown-hover</a>をタブレットで操作している様子です。<p>ちょっとわかりにくいですが、タップしてもドロップダウンメニューが表示しないことがあります。<p><img alt=タブレットでhoverを利用したナビゲーション操作 src=https://i.gyazo.com/f2a8890ba3eba4ea5cc9c964f76faa5c.gif><h2 id=なにが起きてるのか><a href=#なにが起きてるのか aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>なにが起きてるのか？</h2><p>パソコンではhover時に下層メニューが表示します。<p><img alt=パソコンでhoverメニューを操作 src=https://i.gyazo.com/0d9fcd19e4d91aa2ae162cafd58f4bea.gif><p>スマホでは、タブレット同様、hoverという操作は存在しませんが、タップ時に下層メニューが表示します。<br>これは、多くのスマホの場合、 <code>タップしている最中</code> と <code>タップ後</code> が <code>:hover</code> の擬似クラスに割り当てられているためです。<br>よって、CSSの <code>:hoverクラス</code> で実装されていればパソコン同様に操作可能です。<p><img alt="Image from Gyazo"src=https://i.gyazo.com/637e0d8eb1c12e1b4cf2c78277d2a8f2.gif><p>スマホでのタップの場合、CSSの <code>:active</code>, <code>:hover</code>, <code>:focus</code> がどのように反応するかは以前まとめたブログがあるので、そちらを参考にしてください！<p><a href=https://blog.tomoyukikashiro.me/post/how-to-set-active-style-to-button-in-mobile/>How to set :active style to button in mobile</a><p>しかし、タブレットの場合、<a href=http://codepen.io/Tkashiro/full/EaVVxr>このデモ</a>で確認すると、<br>タップ中、タップ後ともに <code>:hoverクラス</code> が割り当てられて <code>いない</code> ようです。<br>よって、 <code>:hoverクラス</code> で実装しているとタブレットでうまく見れません。<table><thead><tr><th>browser<th>hover<th>taping<th>after tapping<tbody><tr><td>Edge on surface go<td>-<td>:active<td>:focus</table><h2 id=どうすればいいのか><a href=#どうすればいいのか aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>どうすればいいのか？</h2><p><code>:hoverクラス</code> の割り当てはブラウザ毎に差があるようなので、 <code>:hover</code> だけに頼らず、<code>hoverが使える端末</code> と <code>hoverが使えない端末</code> でUIや実装を変えるの良いと思っています。<h2 id=よくある間違い><a href=#よくある間違い aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>よくある間違い</h2><pre class=language-css><code class="language-css code-highlight"><span class=code-line><span class="token comment">/* スマホスタイル */</span>
</span><span class=code-line><span class="token comment">/* .... */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> <span class="token number">768</span><span class="token unit">px</span><span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token comment">/* タブレットスタイル */</span>
</span><span class=code-line>  <span class="token comment">/* .... */</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> <span class="token number">1024</span><span class="token unit">px</span><span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token comment">/* パソコンスタイル */</span>
</span><span class=code-line>  <span class="token comment">/* .... */</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><p>よくあるのは、スマホ、タブレット、パソコンをmedia queryのwidthで判定し、パソコン以外では <code>:hover</code> を利用しない方法です。<ul><li>タブレットサイズで <code>:hover</code> が使える端末<li>パソコンサイズで <code>:hover</code> が使えない端末</ul><p>の考慮がここにはありません。。。。。<br>例えば、Surface Goは、上記media queryでは、パソコンサイズですが、タッチスクリーン利用時は、 <code>:hover</code> が動きません。<h2 id=どうやって判断するのか><a href=#どうやって判断するのか aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>どうやって判断するのか？</h2><p><code>hoverが使える端末</code> と <code>hoverが使えない端末</code> の確認には、CSSのInteraction Media Featuresの以下を利用して可能です！<ul><li>Pointing Device Quality<li>Hover Capability<li>Rare Interaction Capabilities</ul><h2 id=端末に関する前提知識><a href=#端末に関する前提知識 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>端末に関する前提知識</h2><p>端末は複数の入力ディバイスを同時に接続できます。<br>例えば、タッチパネルのディバイスにマウスやタブレットペンなどを接続した場合です。<h2 id=pointing-device-quality><a href=#pointing-device-quality aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Pointing Device Quality</h2><p>複数の入力ディバイスが接続されている状態でも <code>プライマリー（優先）</code> 入力ディバイスを判断して、そのポインターの精度を判定するmedia queryです。<pre class=language-css><code class="language-css code-highlight"><span class=code-line><span class="token comment">/* プライマリーがタッチスクリーンのような正確なポインターがないディバイスの場合 */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">pointer</span><span class="token punctuation">:</span> coarse<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token comment">/* プライマリーがマウスのような正確なポインターがあるディバイスの場合 */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">pointer</span><span class="token punctuation">:</span> fine<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token comment">/* coarseやfineでもない場合 */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">pointer</span><span class="token punctuation">:</span> none<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><h2 id=hover-capability><a href=#hover-capability aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Hover Capability</h2><p>複数の入力ディバイスが接続されている状態でも <code>プライマリー（優先）</code> 入力ディバイスを判断して、hoverが利用できるか判定するmedia queryです。<pre class=language-css><code class="language-css code-highlight"><span class=code-line><span class="token comment">/* プライマリー入力ディバイスがhoverを使える場合 */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">hover</span><span class="token punctuation">:</span> hover<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token comment">/* プライマリー入力ディバイスがhoverを使えない場合 */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">hover</span><span class="token punctuation">:</span> none<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><h2 id=rare-interaction-capabilities><a href=#rare-interaction-capabilities aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Rare Interaction Capabilities</h2><p>上記2つは、プライマリーな入力ディバイスしか判断基準にしてませんでしたが、Rare Interaction Capabilitiesを使うと、複数の入力ディバイスがあった場合でも、1つでも該当するかどうかで判定するmedia queryです。<pre class=language-css><code class="language-css code-highlight"><span class=code-line><span class="token comment">/* 入力ディバイスのいずれかに、タッチスクリーンなどポインター精度の低いものが含まれる場合 */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">any-pointer</span><span class="token punctuation">:</span> coarse<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token comment">/* 入力ディバイスのいずれかに、マウスなどポインター精度が高いものが含まれる場合 */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">any-pointer</span><span class="token punctuation">:</span> fine<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token comment">/* 上記以外 */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">any-pointer</span><span class="token punctuation">:</span> none<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><pre class=language-css><code class="language-css code-highlight"><span class=code-line><span class="token comment">/* 入力ディバイスのいずれかに、hover可能なものが含まれる場合 */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">any-hover</span><span class="token punctuation">:</span> hover<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token comment">/* 入力ディバイスのいずれかに、hover不可能なものが含まれる場合 */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">any-hover</span><span class="token punctuation">:</span> none<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><p><code>Pointing Device Quality</code> や <code>Hover Capability</code> はどれか1つに該当する結果になります。<br><code>Rare Interaction Capabilities</code> は複数に該当する結果になり得ます。判断基準が複数入力ディバイスであるためです。<p>例えばタブレットペン付きのSurface goでは、以下のような結果になります。<ul><li><code>@media (poiner: fine)</code>：タブレットペンがあるため<li><code>@media (hover: hover)</code>：タブレットペンがあるため<li><code>@media (any-pointer: fine)</code> と <code>@media (any-pointer: coarse)</code>：タブレットペン(fine)とタッチスクリーン(coarse)があるため<li><code>@media (any-hover: hover)</code> タブレットペンがあるため</ul><p>どのようなディバイスが、どんな結果になるかは、 <a href=https://dev.opera.com/articles/media-features/>Interaction Media Features and their potential</a> を参考ください！<h2 id=どのように活用するのか><a href=#どのように活用するのか aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>どのように活用するのか？</h2><ul><li><code>@media (pointer: coarse)</code> の場合はマウスカーソル精度が低い（タッチスクリーンとか）のでタップエリアを通常より大きくする<li><code>@media (hover: none)</code> の場合は hover UIではない別の方法でUIを提供する</ul><p>なんかが考えられます。<p>実際には、複数入力ディバイスのことを考慮して、`any-pointerやany-hover を使う方がいいでしょう！<br>複数入力ディバイスがある場合（タッチスクリーンとタブレットペン）どちらをユーザーが使ってるかまでは判断できないので、、、<p>hover UIを利用する際は、<ul><li><code>@media (any-pointer: coarse)</code> の場合は別UIを提供</ul><p>のような判断になると思います！<h2 id=javascriptから利用したい場合><a href=#javascriptから利用したい場合 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>JavaScriptから利用したい場合</h2><p><a href=https://developer.mozilla.org/ja/docs/Web/API/Window/matchMedia>matchMedia</a>を利用できます！<pre class=language-javascript><code class="code-highlight language-javascript"><span class=code-line><span class="token dom variable">window</span><span class="token punctuation">.</span><span class="token property-access function method">matchMedia</span><span class="token punctuation">(</span><span class="token string">"(any-hover: coarse)"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token property-access">matches</span>
</span><span class=code-line><span class="token comment">// true or false</span>
</span></code></pre><h2 id=注意><a href=#注意 aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>注意</h2><p><code>@media (hover: on-demand)</code> と <code>@media (any-hover: on-demand)</code> が昔ありましたが、非推奨になっているので使わないように！<p><a href=https://www.chromestatus.com/feature/4719452646014976>Remove “on-demand” value for hover/any-hover media queries. (removed)</a><h2 id=references><a href=#references aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>References</h2><ul><li><a href=https://css-tricks.com/touch-devices-not-judged-size>Touch Devices Should Not Be Judged By Their Size</a></ul>]]></content>
        <published>2019-11-08T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Consider Hover UX for Tablet Device]]></title>
        <id>en-US-consider-hover-effect-for-tablet</id>
        <link href="https://blog.tomoyukikashiro.me/post/consider-hover-effect-for-tablet"/>
        <updated>2022-08-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Sometimes I see site which has hover based navigation does not work correctly when I usse tablet device. so I'll summarize what we need to care about for tablet hover effect.]]></summary>
        <content type="html"><![CDATA[<p>Recently I bought Surface Go for browser testing and use it for my daily life too.<br>Sometime I met some sites which had hover based navigation but it didn’t work correctly on tablet device.<br>This is a capture when I used <a href=https://kybarg.github.io/bootstrap-dropdown-hover/>bootstrap-dropdown-hover</a> which is bootstrap hover based navigation on Surface go.<p>It is difficult to tell what’s going on… I was trying to open dropdown menu but It didn’t work correctly.<p><img alt="operating dropdown menu on tablet device"src=https://i.gyazo.com/f2a8890ba3eba4ea5cc9c964f76faa5c.gif><h2 id=whats-the-matter><a href=#whats-the-matter aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>What’s the matter?</h2><p>When I use laptop the dropdown menu works!!!<p><img alt="operating dropdown menu on laptop"src=https://i.gyazo.com/0d9fcd19e4d91aa2ae162cafd58f4bea.gif><p>When I use mobile the dropdown menu works correctly too.<br>This is because most of mobile browser treat <code>tapping</code> and <code>after tapping</code> state as <code>:hover</code> CSS pseudo-class so if the hover based dropdown menu is implemented using <code>:hover</code> it’s works!!!!!<p><img alt="operating dropdowwn menu on mobile"src=https://i.gyazo.com/637e0d8eb1c12e1b4cf2c78277d2a8f2.gif><p>I wrote blog about this in my past blog post plz check more details.<p><a href=https://blog.tomoyukikashiro.me/post/how-to-set-active-style-to-button-in-mobile/>How to set :active style to button in mobile</a><p>But it doesn’t seems that Edge browser on Surface go treats <code>tapping</code> and <code>after tapping</code> state as <code>:hover</code>.<table><thead><tr><th>browser<th>hover<th>taping<th>after tapping<tbody><tr><td>Edge on surface go<td>-<td>:active<td>:focus<tr><td>mobile Safari<td>-<td>:active<td>:hover</table><p><a href=http://codepen.io/Tkashiro/full/EaVVxr>demo site</a><h2 id=what-should-we-do><a href=#what-should-we-do aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>What should we do?</h2><p>whether the browser treat <code>tapping</code> and <code>after tapping</code> state as <code>:hover</code> CSS pseudo-class or not is different in browsers so we need to detect that users use input device that works <code>:hover</code> or not.<h2 id=common-mistake><a href=#common-mistake aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Common mistake</h2><pre class=language-css><code class="language-css code-highlight"><span class=code-line><span class="token comment">/* for mobile style */</span>
</span><span class=code-line><span class="token comment">/* .... */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> <span class="token number">768</span><span class="token unit">px</span><span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token comment">/* for tablet style */</span>
</span><span class=code-line>  <span class="token comment">/* .... */</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> <span class="token number">1024</span><span class="token unit">px</span><span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line>  <span class="token comment">/* for laptop style */</span>
</span><span class=code-line>  <span class="token comment">/* .... */</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><p>The common mistake is separating style based on device width using <code>min-width</code> or <code>max-width</code> media query then you avoid to use <code>:hover</code> CSS pseudo based UI on tablet device.<br>In this way you don’t consider…<ul><li>Device has tablet width and works <code>:hover</code><li>Device has laptop width but doesn’t work <code>:hover</code></ul><p>For example MS Edge on Surface Go has same width as table but doesn’t work <code>:hover</code> CSS pseudo…<h2 id=how-do-we-detect-the-devices><a href=#how-do-we-detect-the-devices aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>How do we detect the devices?</h2><p>We can detect <code>devices which work :hover</code> and <code>devices which don't work :hover</code> by using <code>Interaction Media Features</code> specs below.<ul><li>Pointing Device Quality<li>Hover Capability<li>Rare Interaction Capabilities</ul><h2 id=prior-knowledge><a href=#prior-knowledge aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Prior knowledge</h2><p>Devices can connect multiple input device such as mouse or tablet pen with touch screen device.<h2 id=pointing-device-quality><a href=#pointing-device-quality aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Pointing Device Quality</h2><p>This is a kind of <code>media query</code> to detect accuracy of the user’s primary pointing device.<pre class=language-css><code class="language-css code-highlight"><span class=code-line><span class="token comment">/* if user's primary input device includes a pointing device of limited accuracy */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">pointer</span><span class="token punctuation">:</span> coarse<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token comment">/* if user's primary input device includes a accurate pointing device */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">pointer</span><span class="token punctuation">:</span> fine<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token comment">/* no pointing device */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">pointer</span><span class="token punctuation">:</span> none<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><h2 id=hover-capability><a href=#hover-capability aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Hover Capability</h2><p>This is a kind of <code>media query</code> to detect hoverable of the user’s primary pointing device.<pre class=language-css><code class="language-css code-highlight"><span class=code-line><span class="token comment">/* if user's primary input device includes a hoverable device */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">hover</span><span class="token punctuation">:</span> hover<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token comment">/* if user's primary input device doesn't includes a hoverable device */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">hover</span><span class="token punctuation">:</span> none<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><h2 id=rare-interaction-capabilities><a href=#rare-interaction-capabilities aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Rare Interaction Capabilities</h2><p><code>Pointing Device Quality</code> and <code>Hover Capability</code> detect the capability of primary input device only so if user connect multiple input devices (like secondary input) those will be ignored.<br>On the other hand, You can detect those capabilities by using <code>any-pointer</code> and <code>any-hover</code> media queries.<br>Those detection are based on multiple input devices.<pre class=language-css><code class="language-css code-highlight"><span class=code-line><span class="token comment">/* if user's primary input device includes "any" pointing device of limited accuracy */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">any-pointer</span><span class="token punctuation">:</span> coarse<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token comment">/* if user's primary input device includes "any" accurate pointing device */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">any-pointer</span><span class="token punctuation">:</span> fine<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token comment">/* no pointing device */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">any-pointer</span><span class="token punctuation">:</span> none<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><pre class=language-css><code class="language-css code-highlight"><span class=code-line><span class="token comment">/* if user's primary input device includes "any" hoverable device */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">any-hover</span><span class="token punctuation">:</span> hover<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span><span class=code-line>
</span><span class=code-line><span class="token comment">/* if user's primary input device doesn't includes "any" hoverable device */</span>
</span><span class=code-line><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">any-hover</span><span class="token punctuation">:</span> none<span class="token punctuation">)</span></span> <span class="token punctuation">{</span>
</span><span class=code-line><span class="token punctuation">}</span>
</span></code></pre><p><code>Rare Interaction Capabilities</code> could match multiple queries because it is based on multiple input devices.<br>For example, The query result of Surface go with tablet pen is below.<ul><li><code>@media (poiner: fine)</code>： because of tablet pen<li><code>@media (hover: hover)</code>： because of tablet pen<li><code>@media (any-pointer: fine)</code> and <code>@media (any-pointer: coarse)</code>： because of tablet pen(fine) and touch screen (coarse)<li><code>@media (any-hover: hover)</code> because of tablet pen</ul><blockquote><p>note: surface tablet pen can hover on elements</blockquote><p>Plz check more detail and full of result of those queries below!!!!<br><a href=https://dev.opera.com/articles/media-features/>Interaction Media Features and their potential</a><h2 id=how-can-we-use-it><a href=#how-can-we-use-it aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>How can we use it?</h2><ul><li><code>@media (pointer: coarse)</code> It might be better to make buttons bigger to tap easier<li><code>@media (hover: none)</code> It might be better to make other UI instead of hover one</ul><p>But those queries don’t consider multiple input device so it could be better to use <code>any-pointer</code> and <code>any-hover</code>.<br>If you want your UI to adapt user’s input device…<ul><li><code>@media (any-pointer: coarse)</code> It might be better to make other UI instead of hover one</ul><h2 id=how-to-query-in-javascript><a href=#how-to-query-in-javascript aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>How to query in JavaScript</h2><p>You can use <a href=https://developer.mozilla.org/ja/docs/Web/API/Window/matchMedia>matchMedia</a> too in JavaScript.<pre class=language-javascript><code class="code-highlight language-javascript"><span class=code-line><span class="token dom variable">window</span><span class="token punctuation">.</span><span class="token property-access function method">matchMedia</span><span class="token punctuation">(</span><span class="token string">"(any-hover: coarse)"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token property-access">matches</span>
</span><span class=code-line><span class="token comment">// true or false</span>
</span></code></pre><h2 id=notes><a href=#notes aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>Notes</h2><p><code>@media (hover: on-demand)</code> and <code>@media (any-hover: on-demand)</code> are old specs so those are deprecated.<p><a href=https://www.chromestatus.com/feature/4719452646014976>Remove “on-demand” value for hover/any-hover media queries. (removed)</a><h2 id=references><a href=#references aria-hidden=true tabindex=-1><span class="icon icon-link"></span></a>References</h2><ul><li><a href=https://css-tricks.com/touch-devices-not-judged-size>Touch Devices Should Not Be Judged By Their Size</a></ul>]]></content>
        <published>2019-11-08T00:00:00.000Z</published>
    </entry>
</feed>