[CSS] 今時の入力フォームバリデーションUI

2025/03/27

CSS

t f B! P L
eyecatch CSSの機能が盛りだくさんになってきました。 EFOの判定もJavascriptを使わなくてもほぼできるようになってきて、 HTML+CSSで、標準的な入力フォームのバリデートチェックが可能になっています。 コツを覚えると、非常に簡易にフロントコーダーレベルでも堅牢なお問い合わせフォームなどが作れるようになります。 最近仕事で作ったバリデートお問い合わせフォームを紹介したいと思います。 できるだけ、コピペで使えるようにコードを書いておいたので、どんどん使ってみてください。 ちなみに、自分用備忘録も兼ねています。

お問い合わせフォームのデモ

  • お問い合わせの種類

  • 名前

  • メールアドレス

  • 内容

ソースコード

HTML

<form name="demo"> <ul class="inputs"> <li> <div class="group"> <p class="name">お問い合わせの種類</p> <select name="genre" required> <option value="">* 選択してください。</option> <option value="1">サイトに関する質問</option> <option value="2">サービスに関する質問</option> <option value="3">その他</option> </select> </div> </li> <li> <div class="group"> <p class="name">名前</p> <input type="text" name="name" required/> </div> </li> <li> <div class="group"> <p class="name">メールアドレス</p> <input type="email" name="mail" required/> </div> </li> <li class="rows"> <div class="group"> <p class="name">内容</p> <textarea name="comment" required></textarea> </div> </li> </ul> <div class="button"> <button class="button-link" type="button" name="save">送信する</button> </div> </form>

CSS

#single-content p{ margin:0!important; } form[name="demo"]{ --color-1 : red; --color-2 : blue; --size-border-radius: 5px; --size-height : 40px; display:block; width:700px; max-width:100%; padding:0 20px; margin:0 auto; } form[name="demo"], form[name="demo"] *{ white-space:normal!important; } form[name="demo"] ul, form[name="demo"] li{ margin:0!important; padding:0!important; list-style:none; } form[name="demo"]:invalid .button button[name="save"]{ background-color:var(--color-1); pointer-events:none; } form[name="demo"] button.sended[name="save"]{ background-color:#AAA; pointer-events:none; } form[name="demo"] .inputs{ display:flex; flex-direction:column; gap:10px; } form[name="demo"] li.spacer{ height:10px; } form[name="demo"] .group{ display:flex; gap:0; width:100%; } form[name="demo"] .group > p{ margin:0; background-color:var(--color-2); color:white; font-size:0.9em; display:flex; align-items:center; justify-content:center; white-space:nowrap; width:150px; min-width:150px; height:var(--size-height); } form[name="demo"] .group > input, form[name="demo"] .group > textarea, form[name="demo"] .group > select, form[name="demo"] .group > label{ border-style:solid; border-color:var(--color-2); border-width:1px 1px 1px 0; padding:10px; flex:1; outline:none; width:100%; height:var(--size-height); background-color:white; } form[name="demo"] .group > textarea{ width:100%; height:200px; border-left-width:1px; border-bottom-left-radius:10px!important; } /** * Required対応 */ form[name="demo"] .rows .group.checkbox-required:not(:has(input[type="checkbox"]:checked)) > p, form[name="demo"] .group:has(input:invalid,select:invalid,textarea:invalid) p{ background-color:var(--color-1); } form[name="demo"] .rows .group.checkbox-required:not(:has(input[type="checkbox"]:checked)) > .flex-column, form[name="demo"] .group:has(input:invalid,select:invalid,textarea:invalid) input, form[name="demo"] .group:has(input:invalid,select:invalid,textarea:invalid) select, form[name="demo"] .group:has(input:invalid,select:invalid,textarea:invalid) textarea{ border-color:var(--color-1); } form[name="demo"] .group *:first-child{ border-radius:var(--size-border-radius) 0 0 var(--size-border-radius); } form[name="demo"] .group *:last-child{ border-radius:0 var(--size-border-radius) var(--size-border-radius) 0; } form[name="demo"] .group .flex-column{ min-height:50px; } form[name="demo"] .group-flex2{ display:flex; gap:10px; } form[name="demo"] .group-flex2 > *{ width:calc(50% - 5px); } /** * Checkbox (label) */ form[name="demo"] label.check{ --size : 20px; display:flex; gap:10px; align-items:center; justify-content:start; padding:5px 10px; cursor:pointer; position:relative; } form[name="demo"] label.check:hover{ color:var(--color-1); } form[name="demo"] label.check::before{ content:""; display:inline-block; border:1px solid black; width:var(--size); min-width:var(--size); height:var(--size); min-height:var(--size); } form[name="demo"] label.check:hover::before{ border-color:var(--color-1) } form[name="demo"] label.check:has(input[type="checkbox"]:checked)::after{ content:""; display:block; position:absolute; width:var(--size); min-width:var(--size); height:var(--size); min-height:var(--size); background-color:black; clip-path:polygon(10% 30%, 50% 60%, 100% 0, 50% 80%, 10% 30%); } form[name="demo"] label.check input{ display:none; } /** * 送信ボタン */ form[name="demo"]:invalid .button{ display:none; } form[name="demo"] .button{ height:80px; display:flex; align-items:center; justify-content:center; } form[name="demo"] .button button{ background-color:var(--color-2); color:white; padding:10px; width:200px; text-align:center; border:0; border-radius:var(--size-border-radius); cursor:pointer; } form[name="demo"] .button button:hover{ background-color:var(--color-1); } @media(max-width:768px){ form[name="demo"] .group-flex2{ flex-direction:column; } form[name="demo"] .group-flex2 .group{ width:100%; } form[name="demo"] .rows .flex-column{ display:flex; } form[name="demo"] .group > p{ font-size:0.8em; } } @media(max-width:500px){ form[name="demo"] .group{ flex-direction:column; } form[name="demo"] .inputs{ gap:20px; } form[name="demo"] .group *:first-child{ border-radius:var(--size-border-radius) var(--size-border-radius) 0 0; border-width: 1px 1px 0 1px; } form[name="demo"] .group *:last-child{ border-radius:0 0 var(--size-border-radius) var(--size-border-radius); border-width: 1px; } form[name="demo"] .rows .group{ height:220px; } }

解説

cssの"要素:invalid"セレクタを使うと、form内でのバリデーションチェック判定をCSSで分岐させる事ができます。 今回は、入力必須項目やメールアドレスなどのバリデート、フォーム内の全ての項目で、入力ミス(漏れ)がなくなれば、送信ボタンを表示する機能を設けています。 他にも、ラジオボタンや、チェックボックスなどの判定もできるので、規定チェックがされていない場合も、invalid判定でうまく機能します。 少し難易度が上がるのは、複数のチェックボックスで、○個以上の項目チェックが必須の場合は、javascriptを使って個数算出をするか、かなり深いCSSを記述するか(今回は説明しません)ですね。 デザインは他にも色々と使えると思うので、今回のソースはあくまでサンプルとして流用してください。

あとがき

結構、わかりやすい入力フォームが作れるでしょ? ホームページではこのおもてなしができる事が、CV(成果)率のアップに深く繋がります。 逆にここで手を抜くと、機会損失という事ですね。 それにしても、JS使わずにここまでできてしまうなんて、いい時代になったな〜。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ