フォームの送信ボタンのinput
タグにアイコン(擬似要素)を加えたかったのですが、できませんでした。それで、ボタンの外をdiv
で囲んで擬似要素を加えました。そしたら、なんということでしょう。ボタンの上に重なったアイコン部分は送信などのイベントが発火しないではありませんか!解決方法はpointer-events
というCSSでした!!
【目次】
- デフォルトの送信ボタンはhover設定がない
- CSSでhover設定を加える
- JSで未入力送信時のクリックイベントを加える
- inputタグには擬似要素が加えられない
- 送信ボタンをdivで囲って擬似要素を当てる
- pointer-eventsで擬似要素のイベントを無効にする
- 最後に
デフォルトの送信ボタンはhover設定がない
フォームの送信ボタンはinput
タグのtype
属性をsubmit
にすると作ることができます。
HTMLのコード
<h1>クリエイター川柳</h1> <form method="" action="" class="senryu"> <input type="text" name="一句" class="ikku"> <input type="submit" value="詠む" class="yomu"> </form>
form
タグ:method
属性もacion
属性も空(データ送信無効)- 上の
input
タグ:type
属性がtext
(1行テキスト) - 下の
input
タグ:type
属性がsubmit
(送信ボタン)
今回はダミーのフォームなのでform
タグのmethod
属性もacion
属性を空にしています。form
タグの詳細は前回記事参照。
※参考:フォームPHPはじめの一歩($_GETと$_POSTの違い) - クモのようにコツコツと
送信ボタンをよりボタンとわかりやすくしたいのでCSSを当ててます。
.yomu { margin: 0 auto; width: 50%; height: 2em; margin: 0 auto; display: block; color: #fff; border: none; background: #666; border-radius: 5px; font-size: 14px; }
詳細は割愛しますが、ボタン幅は50%、文字色は#fff、背景色は#666、角丸は5px、などのスタイルです。
CSSの基本についてはこちら
※参考: 【CSSの基本】書ける前に読む!HTML、CSS、JSの書式-3 - クモのようにコツコツと
できたフォームはこちら。1行川柳を送信する簡単なフォームです。
このままでも一応、フォームの体は成しているのですが、ちょっと問題が。PCブラウザでボタンにカーソルを重ねても矢印になりません。
ボタンはa
タグではなくinput
タグのため、初期値ではhover
設定がないんですな。このままだとボタンということがわかりづらい…*1。
CSSでhover設定を加える
カーソルを重ねたときに送信ボタンとわかるよう、CSSを加えてみましたよ。
.yomu:hover { cursor:pointer; opacity: 0.7; }
.yomu
セレクタの擬似クラス:hover
(カーソルを重ねたときのスタイル)cursor
プロパティをpointer
で、カーソルが矢印にopacity
プロパティを0.7
で不透明度を70%に
カーソルをボタンに重ねてみてください。カーソルが矢印になりましたね!あと、半透明で薄い色にした。「押せそう」感が出てきた!
JSで未入力送信時のクリックイベントを加える
もうひとつよくあるアクション。アラートによるバリデーションをJSのクリックイベントで仕込む。
JSのイベントについてはこちら
※参考:【JSの基本-後編】書ける前に読む!HTML、CSS、JSの書式-5 - クモのようにコツコツと
const ikku = document.querySelector(".ikku"); const yomu = document.querySelector(".yomu"); function yonde() { if(ikku.value === "") { alert('いやん。ちゃんと詠んでね。。'); return false; } } yomu.addEventListener('click', yonde, false);
- 変数
ikku
と.ikku
セレクタの紐付け - 変数
yomu
と.yomu
セレクタの紐付け - 関数
yonde()
設定 - if文、もし
ikku
の値が空だったら いやん。ちゃんと詠んでね。。
というアラートを表示せよ- 戻り値
false
で送信を無効にせよ。 yomu
のクリックイベントで関数yonde()
を実行
送信無効のためにHTMLの送信ボタンにonsubmit
属性を追加。値はreturn 関数名();
。
<input type="submit" value="詠む" class="yomu" onsubmit="return yonde();">
2019/02/17修正
このままだとアラートを閉じたあとに送信が行われるようだったため、送信無効の処理を追加しました。
※参考:JSでsubmitイベント時のreturn falseの扱い方 - ぽんぽこ開発日記
ボタンにイベントを仕込むとこうなった。
テキストを何も入れない状態で送信ボタンを押してみてください。「いやん。ちゃんと詠んでね。。」というアラートが表示されますね。
inputタグには擬似要素が加えられない
さて、ここで送信ボタンに擬似要素::after
で「>」アイコンをつけたくなりました。
.yomu { /*中略*/ potition: relative; } .bg::after { content: ""; display: block; width: 10px; height: 10px; border-top: 2px solid #ccc; border-right: 2px solid #ccc; position: absolute; top: 10px; right: 10px; transform:rotate(45deg); }
これは以前の記事の、CSSだけで作る「>」アイコンの方法です。
※参考:リンクでよくある「>」アイコンを画像じゃなくてCSSだけで作る - クモのようにコツコツと
どうだ?
むむっ!?*2 アイコン出ないじゃん!どうやら、input
タグは擬似要素が非対応のようです。。
送信ボタンをdivで囲って擬似要素を当てる
仕方がないので送信ボタンをdiv
タグで囲ってdiv
タグに擬似要素を当てる方法をとりました。
※参考:input要素に擬似要素を適用させたい | コトダマウェブ
HTMLのコード
<div class="bg"> <input type="submit" value="詠む" class="yomu"> </div>
- 送信ボタン
.yomu
をdiv
タグ.bg
で囲う
CSSのコード
.bg{ position: relative; margin: 0 auto; width: 50%; height: 2em; } .bg::after { content: ""; display: block; width: 10px; height: 10px; border-top: 2px solid #ccc; border-right: 2px solid #ccc; position: absolute; top: 10px; right: 10px; transform:rotate(45deg) }
.bg
のposition
をrelative
にしてサイズなどを設定- 擬似要素
::after
は.bg
に設定する
どうだ!
おお、アイコン出ました!やった!
ただし…アイコンにカーソルを重ねたりクリックしてみてください。細かい部分ですが下記のような問題があります。
- 「>」アイコンにカーソルを乗せるとhoverアクションのスタイルが当たらなくなる
- 「>」アイコンの上でクリックするとアラートのクリックイベントが発火しない(値が空欄のとき)
- 「>」アイコンの上でクリックするとデータ送信自体も無効になる(値が入っているとき)
アイコンは送信ボタンではなくdiv
タグの擬似要素のため、ボタンを覆い隠すように重なっている状態です。そのためアイコン上はボタンのイベントが無効になってしまうのです。しかもデータ送信も行われないとは!これは事故の原因になりそうです。うーむ、困った。。
pointer-eventsで擬似要素のイベントを無効にする
調べたところこの問題を解決してくれる方法がわかりました。CSSのpointer-events
というプロパティです!
※参考:http://nbnote.jp/blog/2012/04/mouse-enabled/
あまり見かけないプロパティですが、値をnone
にするとセレクタのイベントを無効にすることができるようです。これを使うとなぜ解決できるのか?
いまはこんな状態です。
- 送信ボタン
yomu
の上に擬似要素.bg::after
が乗っかってる。 yomu
にはイベントが設定されている。.bg::after
にはイベントが設定されていない。yomu
の上ではyomu
のイベントが発火する。.bg::after
の上ではなにもイベントが発火しない。
ここで.bg::after
にpointer-events: none
を設定すると下記の状態になります。
.bg::after
にpointer-events: none
を設定.bg::after
のイベントは無効になる.bg::after
の上でも.bg::after
のイベントは無視されてその下のyomu
のイベントが発火する
やってみましょう!
.bg::after { /*中略*/ pointer-events: none; }
どうだ?
おお、やりました!
- 「>」アイコン上でもホバーアクションが実行される
- 「>」アイコン上でクリックしてもアラートも表示される(値が空欄のとき)
- 「>」アイコン上でクリックしてもデータ送信が行われる(値が入っているとき)
「>」アイコンというとても小さい面積の細かい設定ではありますが、ボタンとして自然な動きになり、データが未送信などの事故も防げます。より安全なボタンになりました!
最後に
以上、input
タグの機能制限(ホーバー設定がない、擬似要素が無効など)によって起こった事例と、その対策でした。
ちなみにpointer-events
は他にもいろいろなことができそうです。
※参考:https://coliss.com/articles/build-websites/operation/css/css-pointer-events.html
例えばある要素をクリックすると、別の要素でイベントを発火させたりということもCSSだけで実現できます。これまでJSでしかできなかったことがどんどんCSSでできるようになっていっていますねぇ。それではまた!
※参考:ネイティブHTML & CSSやってみたシリーズ
qiita.com