- 投稿日:2019-05-21T23:32:27+09:00
focusで高機能ドロップダウンメニュー(どこをタッチしても閉じる、CSSのみで簡単に)
この記事について
僕のサービスのテストユーザーから、「閉じるボタンでしかメニューが閉じられないのがストレス」と言われたので、どこを触っても閉じるドロップダウンメニューを作りました。
意外とCSSだけで簡単に作れました。(ちなみに部活補助アプリClubCloudの開発を行っています。β版公開中です(宣伝)。)
通常のドロップダウンメニュー
ドロップダウンメニューの閉じ方は主に3つあります。
1はメニューの表示/非表示と紐づいているcheckboxがoffになることで、
2はページ遷移によって(厳密には閉じていない)、
3は主にJavaScriptの操作で
メニューが閉じます。しかし、1~3のように特定のボタンを押さないとメニューを閉じられないのは、ユーザーにとってストレスが大きいようです。
出来れば、画面の関係のない場所を触るだけでメニューが閉じて欲しい!
出来れば、1~3も併用したい!
出来れば、CSSだけで実装したい!出来ます。めちゃ簡単に。
以下、実装ベースの話なのでボタンをラベルと言い換えています。focusを使う!
さて、何を使うかというと、focus要素を使います。
focus要素を使えば、他の場所を触ることで元のfocusが外れるので、それをメニューを閉じるためのトリガーに出来るからです。
つまり、
開くラベル:focus ~ メニュー
というセレクタをうまく使います。ざっくり説明します。
1. 最初、メニューは画面外に隠しておきます。
2.「開くラベル」をクリックすると「開くラベル」にfocusが当たります。
2. 同時に、メニューが出現します。
2. さらに同時に、focusされた「開くラベル」は画面外に固定され、「閉じるラベル」が同じ位置に出現します。
3. メニューは、「開くラベル」にfocusが当たっているときのみ出現するので、画面内のどこをクリックしてもメニューは閉じます。「開くラベル」は画面外にあるのでどこかクリックすれば必ず他の要素にfocusが移るからです。コード
全コード置いておきます。
<label class="menu_label_open" tabindex="0">開く</label> <label class="menu_label_close">閉じる</label> <div class="menu"> <ul> <li><a href="http://google.com">メニュー1</a></li> <li><a href="http://google.com">メニュー2</a></li> <li><a href="http://google.com">メニュー3</a></li> <li><span>キャンセル</span></li> </ul> </div>label{ cursor: pointer; } .menu{ transform: translate3d(0,-200%,0); transition: .3s ease-in-out; -webkit-transition-delay: .1s; transition-delay: .1s; } .menu_label_open:focus ~ .menu{ transform: translate3d(0,0,0); } .menu_label_open:focus ~ .menu_label_close{ display: block; } .menu_label_open:focus{ position: fixed; top:-100%; } .menu_label_close{ display: none; } .menu ul{ display: inline-block; width:100%; padding:0; list-style: none; border:1px solid black; background-color: #fff; text-align: center; cursor: pointer; } .menu ul li:hover{ background-color: rgba(0,0,0,0.2); } .menu ul li:not(:last-child){ border-bottom:0.5px solid black; } .menu ul li span,a{ text-decoration: none; display: block; padding:20px 0; width:100%; }このドロップダウンメニューのキモをいくつか書いておきます。
<!--label要素にfocusを有効にするため--> <label class="menu_label_open" tabindex="0">開く</label>/*メニューを画面外に隠しておく*/ .menu{ transform: translate3d(0,-200%,0); }/*メニューを表示(元の位置に戻す)*/ .menu_label_open:focus ~.menu{ transform: translate3d(0,0,0); }/*メニューが開いているときは「閉じるラベル」を表示*/ .menu_label_open:focus ~ .menu_label_close{ display: block; }/*メニューが開いているときは「開くラベル」を画面外に隠す(display:noneだとfocusが強制的に外れてしまう)*/ .menu_label_open:focus{ position: fixed; top:-100%; }/*メニューが閉じるのを少し待ってあげないと、リンクのクリック終了時にはリンクの位置がズレていてリンクを踏んだことにならない*/ .menu{ -webkit-transition-delay: .3s; transition-delay: .3ms; }開いたままにしたいときは
ちなみに、特定の要素(特にメニューの中の要素)を触ったときにはメニューは開いたままに、という場合は、下記のjqueryコードをHTMLに入れてください。
その要素を触ったときに瞬時に「開くラベル」にfocusを戻すので、メニューは閉じません(transition-delayが効いているのでメニューは少しも動かないで済みます)。<script> $(document).on('click', '.hoge', function(){ $('.menu_label_open').focus() }) </script>まとめ
なかなかいい感じのドロップダウンメニューかなと思います。
checkboxを使うよりもHTMLはスッキリします。
閉じるボタンをずっと使い続けて、他の場所を触っても閉じることに気づくユーザーは少ないかもしれませんが…。
装飾は最低限にしてあるので、ラベルやメニューをいい感じにして使ってみてください!
- 投稿日:2019-05-21T23:14:30+09:00
CSSの圧縮
CSSの圧縮
Water.cssに感化されて開発を始めた私ですが、他の開発者のファイルが小さいのは何故かという素朴な疑問を持ちました。
○○○.min.×××?
ライブラリ等を使っているとしばしば見掛けるこの"○○○.min.×××"という名前。
正直気にもしませんでした。
jQueryにしろ何にしろ、そうあるからそう使っているだけでした。Water.cssを覗き見
すると、minは改行などの無駄な文字列を消し小さくしたものだと気付きました。
そして、これこそがファイルが小さく済む理由なのだと理解しました。実際にしてみる
「CSS 圧縮」
出てきたのは沢山のツールたち。
オンラインで使うものもあれば、コマンドで実行するものもありました。
取り敢えず私は、refresh-sf.comを使ってみました。
すると、1,000文字近く短くなったのです。
状態 行数 文字数 比率 圧縮前 244 3,587 1(△0%) 圧縮後 1 2,227 0.63(△37%) 行数については置いておいて、これはとても驚きました。
しかし納得はできなかった
だが、実際に圧縮後のソースを読んでみると、まだまだ小さくなれそうです。
オンラインなどは汎用的なシステムであるが故に、後から上書きするから取り敢えず最初に0にしておくだとか、そういった処理はなされません。
酷いとこにあっては、同じ値が6箇所も充てられていました。
それを無くすだけでも十分に小さくなります。自力で小さくしてみる
今回私が圧縮を試みたのは開発中のDoc.cssです。
一部の要素に対して作用し、可読性を高める目的で開発を始めました。
だからこそ、こういった規則性があるだとかは自分が一番知っています。
なので私は、自力で小さくしようと考えました。display値で絞る
今回、Doc.cssにより影響を受ける要素はそこまで多くなく、displayがblockであるものに関しては基本的に同じmarginやpaddingを与えています。
なのでまずはdisplayがblockか否かでグループ分けをしてみました。
displayの値 タグ block blockquote,button,code,h1,h2,h3,h4,h5,h6,hr,img,ol,p,table,textarea,ul blockじゃない a,li,tbody,td,tfoot,th,thead,tr tableに関しては諸事情でblockに分類されましたが、のちほど上書きするので気にしません。
特有の値を除外する
例えばcolorだとかoutlineだとか、意図的に一部の要素にのみ充てたい値があります。
それだけを選出し、一時的にファイルの後ろの方に追いやりました。
こうすることで特有でない値が残る
ので、どれが共用可能かがはっきりします。編集後
大分小さくなりました。
作業のために改行はしてありますが、ここで圧縮前後と比較してみます。
状態 行数 文字数 比率 圧縮前 244 3,587 1(△0%) 圧縮後 1 2,227 0.63(△37%) 編集後 38 1,716 0.48(△52%) 圧縮後のファイルから文字数を500近くの削減に成功しました。
では最後に、改行を処理したものも比較してみます。
状態 行数 文字数 比率 圧縮前 244 3,587 1(△0%) 圧縮後 1 2,227 0.63(△37%) 編集後 38 1,716 0.48(△52%) 最終版 1 1679 0.47(△53%) 最終的に、53%近くの削減に成功しました。
感想
共用化可能な部位を探すのは単純に頭の体操になるだけでなく、プログラムを組む上でも大分重要な観点だろうと思いました。
こことここは共用化できる、ここは無理そうだと、そういった判断は実際の仕事の上でも活用できます。
便利なツールに頼るのは楽ですが、たまにはこうして一手間かけてみるのも良いものだなと感じました。最後に
今回、私が開発を進めたCSSはDoc.cssと名付け、Github上に公開した。
特徴としては以下が挙げられる。
- 一部の要素に対し適用される。
- 圧縮版は2kB以下と小型である。
- ドキュメントとして読みやすい。(←私的見解)
サンプルはこちらから確認できるので、是非ともご覧頂き、感想や意見、指摘を頂きたい。
- 投稿日:2019-05-21T17:00:51+09:00
入社した会社名の由来
今日からTECH MASTERの学習を本格スタートしました。
Qiitaにまとめられるほど良い学びが得られた実感がなく
不安な気持ちでこちらを書いています。
(神園先輩のQiitaを参考に、日記風につらつらと書かせていただきます)最初の壁「 div 」
これからお世話になる会社名だというのに
これがプログラミング用語だと今日初めて知り
非常に恥ずかしい気持ちになりました。案の定、私はdivの壁にぶち当たりました…
divとは「 かたまり 」を作るもの
色々なサイトを巡る中でとてもわかりやすいものを発見しました。
<HTMLのdiv classとは?5分でわかる事例付き解説 by Udemy>
https://udemy.benesse.co.jp/development/web/html-div-class.html幸運なことに、同時にぶち当たっていた壁であるclassについても
わかりやすく解説されていました。加藤さんに助けを求めた際に教えてくれた、
”セレクタに特に意味はなく、
引っ越し準備前のからの段ボール箱みたいなものですよ”という例えが、非常にいい得ているなぁ、と感動しました。
聞いた時点ではちゃんと理解していませんでした、ごめんなさい。。。
- 投稿日:2019-05-21T17:00:51+09:00
入社した会社名
今日からTECH MASTERの学習を本格スタートしました。
Qiitaにまとめられるほど良い学びが得られた実感がなく
不安な気持ちでこちらを書いています。
(神園先輩のQiitaを参考に、日記風につらつらと書かせていただきます)最初の壁「 div 」
これからお世話になる会社名だというのに
これがプログラミング用語だと今日初めて知り
非常に恥ずかしい気持ちになりました。※社名の由来は「人生を変える機会(divergence = 分岐点)」
詳しくはこちらで…
https://venturenavi.dreamincubator.co.jp/articles/interview/1346/)案の定、私はdivの壁にぶち当たりました…
divとは「 かたまり 」を作るもの
色々なサイトを巡る中でとてもわかりやすいものを発見しました。
<HTMLのdiv classとは?5分でわかる事例付き解説 by Udemy>
https://udemy.benesse.co.jp/development/web/html-div-class.html幸運なことに、同時にぶち当たっていた壁であるclassについても
わかりやすく解説されていました。加藤さんに助けを求めた際に教えてくれた、
”セレクタに特に意味はなく、
引っ越し準備前のからの段ボール箱みたいなものですよ”という例えが、非常にいい得ているなぁ、と感動しました。
聞いた時点ではちゃんと理解していませんでした、ごめんなさい。。。
- 投稿日:2019-05-21T16:01:45+09:00
Markdownの表でセルのバックグラウンドにカラーを
はじめに
Markdownの表でセルのバックグランドにカラーをつけるやりかたです。
VSCodeのプレビューやPDF出力に反映できます。
忘れないうちに記事にしておきます。前提
- Windows 7 以上のOS
- VSCode(Visual Studio Code)インストール済み
- VSCode拡張機能 Markdown Preview Enhancedインストール済み
- VSCode拡張機能 Markdown PDFインストール済み
元ネタの表
Markdownの記述
№ 色 値 1 white #ffffff 2 black #000000 3 red #ff0000 4 blue #0000ff 5 yellow #ffff00 6 gree #008000 7 orange #ffa500 8 pink #ffc0cb [Markdown]
|№|色|値| |:--:|:--:|:--:| |1|white|#ffffff| |2|black|#000000| |3|red|#ff0000| |4|blue|#0000ff| |5|yellow|#ffff00| |6|gree|#008000| |7|orange|#ffa500| |8|pink|#ffc0cb|htmlの記述
Markdownの記述をhtmlで表現すると下記のようにります。
№ 色 値 1 white #ffffff 2 white #000000 3 red #ff0000 4 blue #0000ff 5 yellow #ffff00 6 green #008000 7 orange #ffa500 8 pink #ffc0cb [html]
<table>~</table>で表を定義します。
行は<tr>でセルは<td>で定義します。
<td>にbgcolorを定義すれば、colorを指定できます。<table> <tr><td>№<td>色<td>値 <tr><td>1<td>white<td>#ffffff <tr><td>2<td>white<td>#000000 <tr><td>3<td>red<td>#0000ff <tr><td>4<td>blue<td>#ffff00 <tr><td>5<td>yellow<td>#ffff00 <tr><td>6<td>green<td>#ffff00 <tr><td>7<td>orange<td>#ffff00 <tr><td>8<td>pink<td>#ffff00 </table>[修正後のhtml]
<table> <tr><td>№<td>色<td>値 <tr><td>1<td bgcolor=white>white<td>#ffffff <tr><td>2<td bgcolor=black><font color=white>black<td>#000000 <tr><td>3<td bgcolor=red><font color=white>red<td>#ff0000 <tr><td>4<td bgcolor=blue><font color=white>blue<td>#0000ff <tr><td>5<td bgcolor=yellow>yellow<td>#ffff00 <tr><td>6<td bgcolor=green><font color=white>green<td>#008000 <tr><td>7<td bgcolor=orange>orange<td>#ffa500 <tr><td>8<td bgcolor=pink>pink<td>#ffc0cb </table>これをそのまま、VSCodeのMarkdownの中に貼り付けると表のセルに色を付けることができます。
QittaのMarkdownプレビューではbgcolorが対応していないようなので、Markdown Preview Enhancedのプレビュー結果を貼り付けます。これはhtmlの普通のやりかたです。
Markdownミックスhtml
Markdownとhtmlのミックスを試してみました。
|№|色|値| |:-:|:-:|:-:| |1<td bgcolor=white>white|#ffffff| |2<td bgcolor=black><font color=white>white|#000000| |3<td bgcolor=red><font color=white>red|#0000ff| |4<td bgcolor=blue><font color=white>blue|#ffff00| |5<td bgcolor=yellow>yellow|#ffff00| |6<td bgcolor=green><font color=white>green|#ffff00| |7<td bgcolor=orange>orange|#ffff00| |8<td bgcolor=pink>pink|#ffff00|[Markdown Preview Enhanced プレビュー]
右に一列ブランクが挿入されます。<td>タグ分が付加されます。
見栄えをすてれば、これでもバックグラウンドにカラーが付いてます。PDFの出力結果
VSCode拡張機能 Markdown PDFの出力結果です。
上がMarkdownとhtmlミックスの結果、下がhtmlのみ記述結果です。
ほぼいけてませんか?まとめ
Markdownの表のセルに色をどうやって付けるのか、自己研究してみました。
もっと簡単でグッドな方法がありそうです。
とりあえず、<td>タグにbgcolorでもいいんじゃない程度の話ですいません。
- 投稿日:2019-05-21T15:02:52+09:00
html要素にfont-size: 62.5%;を指定したのに1.6emが16pxにならなかった話
二度目の投稿です。
今回は失敗からなるほど!!!!!が生まれたので
反省含めて載せます
結論から言えば、何もおかしくないし当たり前でした一箇所だけだしなんでやと思いました
こちらコードです
(base.scss) html { font-size: 62.5%; } (header.scss) h1 { font-size: 3.6rem; margin: 1.6em 0 1.6em 12em; @include mq() { font-size: 2.4rem; margin-left: 1.6em; } }他の部分は思った通りになるんです、、、
検証ツールで実際何pxになっているのかみてみます
57.6px
どうしてええええええええええw
emのコンパイル後の値ってfont-size × emの値だから
emのコンパイル後の値 ÷ emの値で何倍かわかるのでは?57.6 ÷ 1.6 = 36
36…あ、font-size!?となりました
あれでも62.5%で指定したのになぜ、、、、、emとremの知識がごちゃ混ぜになってました
rem
文書のルート要素、つまりhtml要素のfont-sizeを基準にするremはroot要素
em
親要素のfont-sizeを基準に大きさを計算するemは親要素
つまり馬鹿だった
当たり前だった、h1ではfont-sizeを上書きしているから
font-size 36pxを基準にemも計算される
36 × 1.6 = 57.6
何もおかしくなかった
私が書いたコードを忠実に再現してくれただけだったそして学んだfont-sizeを親要素に指定してたらemが思う通りにならないってことは、、、
よく検証ツールとかでみてて疑問だったことがある
なんでいちいちテキスト系divタグとかで囲ってんの???
しかも空だし、わからない、、、これの謎が今回馬鹿をしたことでわかりました
親要素に左右されるので、親要素に当たるところにfont-sizeのrem指定があると良くない
だからdivタグで空の親要素を作ってたのか!!!!!
text系でmarginやpadding取らないようにしようと感じましたすごい初歩的な話ですが間違えて、馬鹿したことで理解が深まりました
これからも頑張ります!
ここまで読んでくれて、ありがとうございます
それでは、また!
- 投稿日:2019-05-21T11:14:41+09:00
Safariの<input type="file">で問題が繰り返し起きるときの対応
はじめに
ファイルアップロードは、かなり鉄板機能なので実装することが多いのですが、ハマりかけたのでログに残しておきます。
エラーまでの経緯
ファイルアップロードのソースは、雰囲気こんな感じです。
inputタグをそのまま使うとダサいので、style="display: none"にして、その代わりにボタンやフォームのクリックイベントでinputタグのクリックイベントを発火します。
<template> <!-- 上は省略 --> <div class="text-xs-center"> <img :src="imageUrl" height="200" v-if="imageUrl"/> <v-text-field color="primary" label="Select Image" @click='pickFile' v-model='imageName' prepend-icon='attach_file'></v-text-field> <input type="file" style="display: none" ref="image" accept="image/*" @change="onFilePicked" > </div> <!-- 下も省略 --> </template> <script> export default { data () { return { imageName: '', contentType: '', imageUrl: '', imageFile: '' } }, methods : { pickFile () { this.$refs.image.click () }, onFilePicked (e) { const files = e.target.files if(files[0] !== undefined) { this.imageName = files[0].name this.contentType = files[0].type // contentType: image/jpegとか if(this.imageName.lastIndexOf('.') <= 0) { return } const fr = new FileReader () fr.readAsDataURL(files[0]) fr.addEventListener('load', () => { this.imageUrl = fr.result this.imageFile = files[0] // this is an image file that can be sent to server... }) } else { this.imageName = '' this.imageFile = '' this.imageUrl = '' } } }, /** いろいろ省略 **/ } </script>開発が一段落し、自分のiPhoneでぽちぽちやっていると、こんな現象に遭遇しました。
問題が起きたため、このWebページが再読込されました。
XXXXXXXXで問題が繰り返し起きました。調べた
Safariでは、display:noneに問題があるらしいです。なので、『inputタグはdisplay:noneではなく、divで囲んでheightとwidthを0にせよ』とのことでした。
<template> <!-- 上は省略 --> <div class="text-xs-center"> <img :src="imageUrl" height="200" v-if="imageUrl"/> <v-text-field color="primary" label="Select Image" @click='pickFile' v-model='imageName' prepend-icon='attach_file'></v-text-field> <div class="hiddenfile"> <!-- ←これで囲む --> <input type="file" ref="image" accept="image/*" @change="onFilePicked" > </div> </div> <!-- 下も省略 --> </template> <script> /** 変更なし **/ </script> <style scoped> .hiddenfile { width: 0px; height: 0px; overflow: hidden; } </style>う〜ん何故だろう、、、
むかしからdisplay:noneが常識かつ定石だと思っていましたら、Safariさんは違ったようです。めでたし。
参考記事
- 投稿日:2019-05-21T10:45:13+09:00
【jQuery】異なるバージョンを共存させる
ひとつのリソースに複数のコーダーが関わってるとたまにあるやつ。
これを導入したら既存のギミックが動作しなくなった・・・みたいな。解決方法
$.noConflict()
を使う<script type="text/javascript" src="https://code.jquery.com/jquery-1.8.2.min.js"></script> <script type="text/javascript"> $182 = $.noConflict(true); </script> <script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>これで、$182はバージョン1.8.2、$はバージョン3.3.1のjQueryとして使い分けることが可能。