- 投稿日:2020-12-04T23:44:34+09:00
htmlどれがタグでどれが要素か、各名称
htmlのタグとか要素、cssのプロパティー、プロパティーの値とか何が何かよくわからなくごちゃごちゃになると思うのでまとめました。
要素
//要素 <head> <meta> <title> <link> <style> </head> <body> <footer> <header> <main> <nav> <section>タグ
href
classなど要素の次に書くのをタグという
<a href="`"></a> <div class="#"></div>フッタータグは
<footer> <small> @ 2020 example.com </small>セレクター、プロパティ、規則セット
セレクター
プロパティー: プロパティー値;div {
coloer: red;
font-size: 80px;
右左2つセットで宣言
3つセットで規則セットdiv { color: red; font-size: 80px; }
- 投稿日:2020-12-04T23:15:53+09:00
railsで画像をファイルに配置して、表示させ、装飾させる方法
- 投稿日:2020-12-04T20:49:41+09:00
flexboxで横並びにしたコンテンツの中の最後の要素(ボタン等)は下揃えにする方法
どうも7noteです。横並びコンテンツの各要素の最後だけ下揃えにする方法について
先日ツイッターで見つけた画期的なアイデア・スタイルです。正直ちょっと感動しました。
ガタガタになってしまうところをきれいに並べることができます!
ソース
index.html<ul> <li> <figure class="thumb"> <img src="sample.png" alt="画像"> </figure> <p class="text">テキストが入ります。テキストが入ります。テキストが入ります。</p> <div class="btn">ボタン</div> </li> <li> <figure class="thumb"> <img src="sample.png" alt="画像"> </figure> <p class="text">テキストが入ります。</p> <div class="btn">ボタン</div> </li> <li> <figure class="thumb"> <img src="sample.png" alt="画像"> </figure> <p class="text">テキストが入ります。</p> <div class="btn">ボタン</div> </li> </ul>style.cssul { margin: 0 0 30px; display: flex; flex-wrap: wrap; justify-content: space-between; } ul li { width: 200px; /* 各コンテンツの横幅 */ border: 1px solid #000; /* 各コンテンツのborder */ padding: 10px; /* 余白の指定 */ display: flex; /* 【重要】フレックスボックスにする */ flex-direction: column; /* 【重要】縦並びにする */ } ul li .text { background: #ccc; /* 背景色にグレーを指定 */ margin: 0 0 10px; /* 下に10pxの余白 */ padding: 5px; /* 余白5pxを指定 */ } ul li .btn { border: 1px solid #000; /* borderを指定 */ border-radius: 20px; /* 角丸にする */ text-align: center; /* 文字を中央寄せ */ margin-top: auto; /* 【重要】上に取れるだけの余白 */ }解説
まず各要素をフレックスボックスにして、
flex-direction: column;
を指定し、liの中の要素を縦並びにする。
そして、下揃えにしたい最後の要素に対して、margin-top: auto;
を指定することで、最大余白を自動で取得するので、それ以外の要素の高さに依存せずに下揃えにすることが可能になります。まとめ
CSSの様々な組み合わせで、まだまだ知らない組み方が出るのでコーディングは本当に奥が深いし面白いなと思います。
日々精進あるのみです。おそまつ!
~ Qiitaで毎日投稿中!! ~
【初心者向け】HTML・CSSのちょいテク詰め合わせ
- 投稿日:2020-12-04T15:08:22+09:00
【Shopify】liquidを編集してコンタクトフォームをカスタマイズする方法
概要
Shopifyでは、コンタクトフォームをデフォルト機能で簡単に実装することができます。しかし、デフォルト機能で実装することができるコンタクトフォームは、名前・電話番号・メールアドレス・メッセージ必要最低限の情報を入力する欄しかありません。
そこで、今回はliquidファイルを編集して、コンタクトフォームを編集する方法を解説します。
クイックスタート
今回は、すでに作成済みのデモサイトを用いて解説します。使用テーマは「Debut」です。使用しているテーマによってコードは若干異なります。基本的な構成は同じなので、流用は可能です。
なお、コンタクトフォームの実装方法については、省略します。詳しい実装方法が知りたい方は、こちらの記事をご覧ください。
【Shopifyマスターへの道】#11 コンタクトフォームを作成しよう
Shopifyマスターへの道は、Shopifyの構築を網羅的に解説しているシリーズ連載になリます。興味があれば、そちらも覗いてみてください。
編集するliquidファイルは、
page.contact.liquid
です。ここにコードを追加することで、コンタクトフォームに入力欄を追加していきます。
page.contact.liquid
の構造についてまず、
page.contact.liquid
の構造について理解します。まずコードの全体像をみます。<div class="page-width"> <div class="grid"> <div class="grid__item medium-up--five-sixths medium-up--push-one-twelfth"> <div class="section-header text-center"> <h1>{{ page.title }}</h1> </div> {% if page.content.size > 0 %} <div class="rte"> {{ page.content }} </div> {% endif %} <div class="contact-form form-vertical"> {%- assign formId = 'ContactForm' -%} {% form 'contact', id: formId %} {% include 'form-status', form: form, form_id: formId %} <div class="grid grid--half-gutters"> <div class="grid__item medium-up--one-half"> <label for="{{ formId }}-name">{{ 'contact.form.name' | t }}</label> <input type="text" id="{{ formId }}-name" name="contact[{{ 'contact.form.name' | t }}]" value="{% if form[name] %}{{ form[name] }}{% elsif customer %}{{ customer.name }}{% endif %}"> </div> <div class="grid__item medium-up--one-half"> <label for="{{ formId }}-email">{{ 'contact.form.email' | t }} <span aria-hidden="true">*</span></label> <input type="email" id="{{ formId }}-email" name="contact[email]" autocorrect="off" autocapitalize="off" value="{% if form.email %}{{ form.email }}{% elsif customer %}{{ customer.email }}{% endif %}" aria-required="true" {%- if form.errors contains 'email' -%} class="input--error" aria-invalid="true" aria-describedby="{{ formId }}-email-error" {%- endif -%} > {%- if form.errors contains 'email' -%} <span id="{{ formId}}-email-error" class="input-error-message"> <span class="visually-hidden">{{ 'general.accessibility.error' | t }} </span> {% include 'icon-error' %} <span>{{ form.errors.translated_fields['email'] | capitalize }} {{ form.errors.messages['email'] }}.</span> </span> {%- endif -%} </div> </div> <label for="{{ formId }}-phone">{{ 'contact.form.phone' | t }}</label> <input type="tel" id="{{ formId }}-phone" name="contact[{{ 'contact.form.phone' | t }}]" pattern="[0-9\-]*" value="{% if form[phone] %}{{ form[phone] }}{% elsif customer %}{{ customer.phone }}{% endif %}"> <label for="{{ formId }}-message">{{ 'contact.form.message' | t }}</label> <textarea rows="10" id="{{ formId }}-message" name="contact[{{ 'contact.form.message' | t }}]">{% if form.body %}{{ form.body }}{% endif %}</textarea> <input type="submit" class="btn" value="{{ 'contact.form.submit' | t }}"> {% endform %} </div> </div> </div> </div>コードを読んでみると、
page.contact.liquid
は主に3つのブロックからなっています。
- タイトルを表示させるブロック
- コンテンツの内容を表示させるブロック
- コンタクトフォームを表示させるブロック
それぞれのコードをみましょう。
タイトルを表示させるブロック
次のコードで、ページを作成する際に入力したタイトルを表示させています。
<div class="section-header text-center"> <h1>{{ page.title }}</h1> </div>
<h1>
タグのなかで{{ page.title }}
を呼び出しています。コンテンツの内容を表示させるブロック
次のコードで、ページを作成した際に入力したコンテンツの内容を表示しています。
{% if page.content.size > 0 %} <div class="rte"> {{ page.content }} </div> {% endif %}
{% if page.content.size > 0 %}
でコンテンツの内容が入力されているか判定しています。true
の場合、{{ page.content }}
コンテンツの内容を呼び出して表示しています。コンタクトフォームを表示させるブロック
次のコードで、コンタクトフォームの表示を実装しています。
<div class="contact-form form-vertical"> {%- assign formId = 'ContactForm' -%} {% form 'contact', id: formId %} {% include 'form-status', form: form, form_id: formId %} <div class="grid grid--half-gutters"> <div class="grid__item medium-up--one-half"> <label for="{{ formId }}-name">{{ 'contact.form.name' | t }}</label> <input type="text" id="{{ formId }}-name" name="contact[{{ 'contact.form.name' | t }}]" value="{% if form[name] %}{{ form[name] }}{% elsif customer %}{{ customer.name }}{% endif %}"> </div> <div class="grid__item medium-up--one-half"> <label for="{{ formId }}-email">{{ 'contact.form.email' | t }} <span aria-hidden="true">*</span></label> <input type="email" id="{{ formId }}-email" name="contact[email]" autocorrect="off" autocapitalize="off" value="{% if form.email %}{{ form.email }}{% elsif customer %}{{ customer.email }}{% endif %}" aria-required="true" {%- if form.errors contains 'email' -%} class="input--error" aria-invalid="true" aria-describedby="{{ formId }}-email-error" {%- endif -%} > {%- if form.errors contains 'email' -%} <span id="{{ formId}}-email-error" class="input-error-message"> <span class="visually-hidden">{{ 'general.accessibility.error' | t }} </span> {% include 'icon-error' %} <span>{{ form.errors.translated_fields['email'] | capitalize }} {{ form.errors.messages['email'] }}.</span> </span> {%- endif -%} </div> </div> <label for="{{ formId }}-phone">{{ 'contact.form.phone' | t }}</label> <input type="tel" id="{{ formId }}-phone" name="contact[{{ 'contact.form.phone' | t }}]" pattern="[0-9\-]*" value="{% if form[phone] %}{{ form[phone] }}{% elsif customer %}{{ customer.phone }}{% endif %}"> <label for="{{ formId }}-message">{{ 'contact.form.message' | t }}</label> <textarea rows="10" id="{{ formId }}-message" name="contact[{{ 'contact.form.message' | t }}]">{% if form.body %}{{ form.body }}{% endif %}</textarea> <input type="submit" class="btn" value="{{ 'contact.form.submit' | t }}"> {% endform %} </div>
{% form 'contact', id: formId %}
から{% endform %}
までが。ストアに送信される部分になります。
この部分には、4つの<input>
タグがあり、それぞれ名前・Eメール・電話番号・メッセージを受け取ることができます。つまり、この
{% form 'contact', id: formId %}
から{% endform %}
の間に、<input>
タグなどを増やすことで、コンタクトフォームをカスタマイズすることができます。名前のフリガナの入力欄を作成する
シンプルな入力欄を増やします。フリガナを入力するための
<input>
タグを書きます。<input>
タグの書き方は、HTMLの知識になってくるので、ここでの詳しい説明は割愛します。名前の横に配置したいので、名前の
<div>
タグとEメールの<div>
タグの間に記述します。<div class="grid__item medium-up--one-half">
という<div>
タグで囲うことで、半分のカラム幅の入力欄を実装できます。以下のコードを追記しましょう。
<div class="grid__item medium-up--one-half"> <label for="{{ formId}}-furigana">フリガナ</label> <input type="text" id="{{ formId}}-furigana" name="contact[フリガナ]" > </div>このように追記できたら、一旦コードを保存しプレビュー画面で確認します。
このように実装できました。Eメールの隣が空いてしまっているので、そこに新たな入力欄を追加します。
性別の選択欄を作成する
<select>
タグを用いて、性別の選択欄を作成します。<select>
タグを用いると、ドロップダウン式の選択欄を作成することができます。<select>
タグの中に<option>
タグで選択肢を指定していきます。以下のコードをEメールの入力欄の後ろに記述してください。
<div class="grid__item medium-up--one-half"> <label for="{{ formId}}-sex" >性別</label> <select id="{{ formId}}-sex" name="contact[性別]"> <option>--選択してください--</option> <option>男性</option> <option>女性</option> <option>その他</option> </select> </div>追記したらコードを保存し、プレビュー画面で確認しましょう。
電話番号の入力欄を削除する
元からある入力欄を削除してみましょう。例として電話番号の入力欄を削除してみます。
以下のコードを削除してください。
<label for="{{ formId }}-phone">{{ 'contact.form.phone' | t }}</label> <input type="tel" id="{{ formId }}-phone" name="contact[{{ 'contact.form.phone' | t }}]" pattern="[0-9\-]*" value="{% if form[phone] %}{{ form[phone] }}{% elsif customer %}{{ customer.phone }}{% endif %}">削除したら保存し、プレビュー画面で確認します。
問題なく削除することができました。
チェックボックスを作成する
次に、
<input>
タグのtype="checbox"
属性を使って、チェックボックスを実装します。以下のコードを追記します。
<p>お問い合わせ内容を選択してください(複数選択可)</p> <label for="{{ formId}}-inquirydetails"><input type="checkbox" id="{{ formId }}-inquirydetails" name="contact[お問い合わせ内容]" value="お仕事のご依頼">お仕事のご依頼</label> label for="{{ formId}}-inquirydetails"><input type="checkbox" id="{{ formId }}-inquirydetails" name="contact[お問い合わせ内容]" value="無料相談">無料相談</label> <label for="{{ formId}}-inquirydetails"><input type="checkbox" id="{{ formId }}-inquirydetails" name="contact[お問い合わせ内容]" value="その他">その他</label><br>このようにチェックボックスを実装することができました。
以上で、フォームの編集は終了です。
送信できることを確認する
送信フォームが正常に送信することができるか、確認します。作成したコンタクトフォームで、必要事項を入力し送信します。
以下のようなメッセージが表示されれば送信は、正常に完了しています。
最後まで読んでいただきありがとうございました。
- 投稿日:2020-12-04T09:56:15+09:00
Less CSSで@importを展開せずにそのままCSSにする方法
Less CSSで
@import
を展開せずにそのままCSSにする方法ちょっと詰まったので備忘録として。
Less CSSで
@import
をそのまま使うと、外部のサイトでもインポートして展開されてしまう。lessc
で変換しようにも社内のプロキシ環境で使うとコネクションエラーが発生するし、Google Fontsを使うときも展開しては欲しくない。less.js
に動的に変換させればよいのだが、Internet Explorer 11では動かない。これは困った。探していたら、ちゃんとマニュアル (英語) に書いてあった。この
css
オプションを使えば展開されずにそのままCSSに出力される。sample.less/* フォント設定 */ @import (css) url(https://fonts.googleapis.com/css?family=Noto+Sans+JP|Noto+Serif+JP|Roboto+Mono&display=swap);sample.css/* フォント設定 */ @import url(https://fonts.googleapis.com/css?family=Noto+Sans+JP|Noto+Serif+JP|Roboto+Mono&display=swap);Microsoftが自社サービスのInternet Explorerサポート終了を打ち出したので、Internet Explorerはもうそろそろ考えなくても良いかな。
- 投稿日:2020-12-04T09:56:15+09:00
Lessで@importを展開せずにそのままCSSにする方法
Lessで
@import
を展開せずにそのままCSSにする方法ちょっと詰まったので備忘録として。
Lessで
@import
をそのまま使うと、外部のサイトでもインポートして展開されてしまう。lessc
で変換しようにも社内のプロキシ環境で使うとコネクションエラーが発生するし、Google Fontsを使うときも展開しては欲しくない。less.js
に動的に変換させればよいのだが、Internet Explorer 11では動かない。これは困った。探していたら、ちゃんとマニュアル (英語) に書いてあった。この
css
オプションを使えば展開されずにそのままCSSに出力される。sample.less/* フォント設定 */ @import (css) url(https://fonts.googleapis.com/css?family=Noto+Sans+JP|Noto+Serif+JP|Roboto+Mono&display=swap);sample.css/* フォント設定 */ @import url(https://fonts.googleapis.com/css?family=Noto+Sans+JP|Noto+Serif+JP|Roboto+Mono&display=swap);Microsoftが自社サービスのInternet Explorerサポート終了を打ち出したので、Internet Explorerはもうそろそろ考えなくても良いかな。
- 投稿日:2020-12-04T09:56:15+09:00
Lessで@importを展開しないでそのままCSSにする方法
ちょっと詰まったので備忘録として。
Lessで
@import
をそのまま使うと、外部のサイトでもインポートして展開されてしまう。lessc
で変換しようにも社内のプロキシ環境で使うとコネクションエラーが発生するし、Google Fontsを使うときも展開しては欲しくない。less.js
に動的に変換させればよいのだが、Internet Explorer 11では動かない。これは困った。探していたら、ちゃんとマニュアル (英語) に書いてあった。この
css
オプションを使えば展開されずにそのままCSSに出力される。sample.less/* フォント設定 */ @import (css) url(https://fonts.googleapis.com/css?family=Noto+Sans+JP|Noto+Serif+JP|Roboto+Mono&display=swap);sample.css/* フォント設定 */ @import url(https://fonts.googleapis.com/css?family=Noto+Sans+JP|Noto+Serif+JP|Roboto+Mono&display=swap);Microsoftが自社サービスのInternet Explorerサポート終了を打ち出したので、Internet Explorerはもうそろそろ考えなくても良いかな。
- 投稿日:2020-12-04T09:36:32+09:00
odoo - Fontの変更
Custom font という仕組み。
自動生成される web.assets_backend.css の body { Font-Family } に IPAmjMincho を追加。
font-family: "Odoo Unicode Support Noto", "Lucida Grande", Helvetica, Verdana, Arial, sans-serif;生成されたcss
http://localhost:8069/web/content/235-a50e7a9/web.assets_backend.css"Odoo Unicode Support Noto"が出現する箇所。
/* /web/static/src/scss/import_bootstrap.scss defined in bundle 'web.assets_backend' /
/ /web/static/src/scss/webclient.scss defined in bundle 'web.assets_backend' */
.o_web_accesskey_overlay{font-family: "Odoo Unicode Support Noto", "Lucida Grande", Helvetica, Verdana, Arial, sans-serif;}
addons\web\static\src\scss\import_bootstrap.scss???
addons\web\static\src\scss\webclient.scss.o_web_accesskey_overlay { font-family: $font-family-sans-serif; }addons\web\static\src\scss\bootstrap_overridden.scss// Fonts // // Font, line-height, and color for body text, headings, and more. $font-family-sans-serif: o-add-unicode-support-font(("Lucida Grande", Helvetica, Verdana, Arial, sans-serif), 1) !default;addons\web\static\src\scss\utils.scss// Odoo defines a limited Noto font-family for a small variety of unicode // characters that are not necessary defined in the user system or even defined // but not properly readable. This function allows to add this font family in a // given font list. // // @param {list} $font - a list of font names ending with the generic one. // @param {integer} [$index] - the position where to add the support font, if // not given, it will be placed before the generic one. @function o-add-unicode-support-font($font, $index: false) { @if $index == false { $index: length($font); } $-with-support-font: (); @for $i from 1 through length($font) { @if $i == $index { $-with-support-font: append($-with-support-font, 'Odoo Unicode Support Noto', $separator: comma); } $-with-support-font: append($-with-support-font, nth($font, $i), $separator: comma); } @return $-with-support-font; }
- 投稿日:2020-12-04T07:13:24+09:00
Tailwind CSS 2.0で追加された機能全部使ってデモページを作る
この記事は弥生 Advent Calendar 2020の4日目の記事です。
さて、2020年11月19日にTailwind CSSのver2.0がリリースされました???
https://blog.tailwindcss.com/tailwindcss-v2それを記念して? Tailwind CSS 2.0で追加された機能全部入れてデモページを作ってみました。アドベントカレンダー記事というのもあり、Qiitaアドベントカレンダーをインスパイアした形で作っています。
TailwindCSSとは何ぞやという話は、いろんな方がすでにたくさん記事を書いていますので割愛します。
(ご参考)
作ったもの
アドベントカレンダーのページっぽく、ヘッダー、タイトル、カレンダー、フッターを含んだ1ページです。レスポンシブ、ダークモード対応しています。生のCSSは1行も書いていません。全てTailwindCSSだけで作っています。
なお、Tailwind Playというサンドボックス環境に公開していますので、こちらから作ったものとソースコードがみれます。(開いたらビルドが走るみたいですので、初回表示は遅いです。)
https://play.tailwindcss.com/euCH5tu0IA?layout=horizontalchromeの開発ツールでブラウザのダークモード切り替えが出来ますので、遊んでいただければと思います。(Tailwind Playヘッダーの月と太陽マーク押してもスイッチしないので注意)
Tailwind CSS 2.0で追加された機能
ニュースリリースからの引用です。
- All-new color palette
- Dark mode support
- Extra wide 2XL breakpoint
- New outline ring utilities
- Utility-friendly form styles
- Default line-heights per font-size
- Extended spacing, typography, and opacity scales
- Use @apply with anything
- New text overflow utilities
- Extend variants
- Group-hover and focus-within by default
- Default transition duration and easing curve
- Incompatibility with IE11
これらを全部デモページに埋め込みましたので、一つ一つ実装したものを見ていきたいと思います。
All-new color palette
デフォルトで用意されているカラーパレットが全面的に刷新され、今までの10色、9段階の明暗のカラーパレットから、22色、10段階の明暗が用意されました。
デモページではcyan
を使ってみました。色の追加はtailwind.config.jsという設定ファイルをいじります。tailwind.config.jsconst colors = require('tailwindcss/colors') module.exports = { theme: { colors: { cyan: colors.cyan, }, }, }<span class="block text-cyan-600 dark:text-cyan-500 xl:inline text-6xl"> 2020 </span>色はこんな感じです。いい色ですね。
Dark mode support
簡単にダークモード対応出来るようになりました。設定ファイルに1行追加して、
tailwind.config.jsmodule.exports = { darkMode: 'media', // ... }<header class="h-16 bg-white dark:bg-gray-800 px-4"> </header>こんな感じで
dark:
ディレクティブを使って記述すれば、ブラウザのダークモード設定時にはdark:
のスタイルが使用されます。簡単!すごい!Extra wide 2XL breakpoint
1536px以上の画面サイズに対する新しいブレイクポイント
2xl:
が追加されました。デモページでは画面サイズを1536px以上にすると文字が出てくるようにしてみました。<p class="hidden 2xl:block text-9xl text-center font-bold my-20">Too wide and Too Big!!</p>New outline ring utilities
入力フォームなどでフォーカスされた時に出てくる黒い枠のところをoutline ringと呼んでいます。このスタイルが増えました。
<input type="text" placeholder="ユーザーID" class="rounded border mr-2 px-2 py-1 focus:outline-none focus:ring-4 focus:ring-cyan-300 focus:ring-opacity-75" />Utility-friendly form styles
ブラウザごとに異なるフォームデザインをノーマライズ・リセットしてTailwindのユーティリティクラスをシンプルに使用できるようになりました。
@tailwindcss/forms
プラグインを使用するようにconfigファイルに記述します。tailwind.config.jsmodule.exports = { // ... plugins: [require('@tailwindcss/forms')], }<input type="checkbox" class="rounded-full mx-1 text-cyan-600 focus:outline-none" /> <input type="checkbox" class="rounded-full mx-1 text-cyan-600 focus:outline-none" /> <input type="checkbox" class="rounded-full mx-1 text-cyan-600 focus:outline-none" /> <input type="checkbox" class="rounded-full mx-1 text-cyan-600 focus:outline-none" /> <input type="checkbox" class="rounded-full mx-1 text-cyan-600 focus:outline-none" />
ユーザビリティは悪いですが、丸いチェックボックスなんかも作れますし、チェックした色も簡単に変えられます。これ、地味に凄くないですか?今まではチェックボックスの色変えようと思ったらCSSたくさん書いて自前でチェックの形作ってました。それがtext-cyan-600
だけで色変わります。Default line-heights per font-size
フォントサイズを選んだ時にデフォルトでLine Heightも設定されるようになりました。
<p class="text-xl">This will have a line-height of 1.75rem automatically.</p>Extended spacing, typography, and opacity scales
デフォルトで選べるサイズが増えました。
96
とかはあまり使わないと思いますが、7
とかはたまに使いたい場面があったので良かったと思います。テキストサイズも
9xl
まで用意されています。ちなみにブレイクポイントのところで出した「Too Big!」の文字はtext-9xl
を使っています。
Use @apply with anything
普通のセマンティックなクラスを作りたい場合、
@apply
ディレクティブを使って共通化できましたが、今まではfocus:
やhover:
などの一部の機能が使えませんでした。今回から全ての機能を@apply
に使用できます。もちろんdark:
もです。<button class="btn-cyan">参加登録</button>.btn-cyan { @apply bg-cyan-600 dark:bg-cyan-500 text-white text-sm px-2 py-1 rounded mt-2 hover:bg-cyan-700; }New text overflow utilities
今まではテキストが要素からはみ出した時に
truncate
しかありませんでしたが、overflow-ellipsis
とoverflow-clip
が使えるようになりました。ただ、これは日本語には使えないかもしれないです。英語はうまく...
が入りましたが、日本語はうまくいきませんでした。<div class="h-20 w-24 overflow-hidden overflow-ellipsis text-xs mt-1"> <a class="text-cyan-600 dark:text-cyan-500 hover:underline cursor-pointer">This is a long long English Sentences and LongLongLongLongOneWord</a> </div>Group-hover and focus-within by default
グループを指定して、その要素がホバーされたら子要素にもホバー時の挙動が適用できます。
<td class="group h-40 w-1/7 border-r text-gray-600 dark:text-gray-300 hover:bg-gray-200"> <div class="flex flex-col h-full p-2"> <div class="text-center">8</div> <div class="flex items-center text-xs mt-2 hover:underline"> <div class="h-5 w-5 rounded-full bg-gray-500 group-hover:bg-cyan-600 mr-1"></div> <a href="#" class="text-cyan-600 group-hover:text-gray-500 dark:text-cyan-500"> User Name </a> </div> <div class="text-xs text-gray-400 mt-1 group-hover:text-red-400">group hover確認</div> </div> </td>Default transition duration and easing curve
transitionとeaseのデフォルト値を定義できるようになりました。tailwind.config.jsに
transitionDuration = 1000ms
を試しに追加してみます。tailwind.config.jsmodule.exports = { darkMode: "media", theme: { //...// transitionDuration: { DEFAULT: '1000ms', }, transitionTimingFunction: { DEFAULT: 'cubic-bezier(0.4, 0, 0.2, 1)', }, }, variants: {}, plugins: [require('@tailwindcss/forms')], }<button class="bg-cyan-600 rounded text-white px-3 py-2 transition hover:bg-white hover:text-cyan-600 shadow-lg focus:outline-none">招待する</button>
transition
クラスを追加するだけでいい感じになりました。アニメーションの一貫性を維持しやすくなりますね。
以上!
2.0で追加された機能を全部試してみました。
個人的にはダークモードがやっぱり楽すぎるのと、
@apply
全機能対応が嬉しかったです。最後までお付き合いいただきありがとうございました。
- 投稿日:2020-12-04T05:34:49+09:00
FNS歌謡祭のHPに実装されているアニメーションを自分も作成したい!!! ハンズオン!!
はじめに
お疲れ様です。
DMM WEBCAMP Advent Calendar 2020の4日目を担当させていただきます。
メンターの@koseiinfratopです。みなさん先日OAされたFNS歌謡祭はみましたか?
バンタンや3代目JSBなど豪華アーティストが出演されていて本当におもしろい番組でしたね。なかでもユーミンと嵐のコラボは感動的でした。
OA当日僕はふと思いました。嵐はいつごろ出番なのだろうかと。そこでFNS歌謡祭の公式HPを訪れたことで今回のAdvent Calendarで何を書くがが決定しました。
一度公式HPを訪れていただけるとわかるのですが、アーティストの画像にカーソルを乗せてみてください。カーソルを乗せると薄黒いボックスとアーティスト名が出てきます。僕は疑問に思いました。これはどうやって実装しているのかと。。。
ということで今回は疑問に思ったことを解消するためにFNSのHPのようにカーソルを画像に載せるとアニメーションが発火するような機能を実装しようと思います。
- 開発効率を上げたかったため今回はホットリロードが可能なReact.jsでコーディングしました。
- しれっとiTunesAPIも使用しています。
1.html(js)を記述
music.js...*iTunesAPI関係の処理は割愛 return( <div className="searchresult"> {artistData.map(artistdata => ( <ArtistData key={artistdata.CollectionId.toString()} id={artistdata.CollectionId} name={artistdata.ArtistName} album={artistdata.AlbumName} albumUrl={artistdata.AlbumUrl} genre={artistdata.AlbumGenre} release={artistdata.AlbumRelease} /> ) )} </div> );artistdata.jsimport React from 'react'; const ArtistData = (props) => { return( <div className={props.id ? 'album': 'noalbum'}> <div className="flex"> <img src={props.albumUrl} alt={props.album} className="albumImage"/> <div> <p>ジャンル: <b>{props.genre}</b></p> </div> </div> <div className="mask"> <div className="caption">{props.album}</div> </div> <div> <p>アーティスト: <b>{props.name}</b></p> <p>アルバム名: <b>{props.album}</b></p> <p>リリース日: <b>{props.release}</b></p> </div> </div> ); } export default ArtistData2.CSSの記述
*ポイントだけコメントアウトを用いて解説します。
music.css.album { width: 300px; height: 230px; /* overflow・・・アルバムクラスのdivタグ範囲内に内容が収まらない場合(今回で言うとmaskクラスのdivタグがはみ出る)の処理 overflow: hidden; /* 表示させないようにしている */ margin: 10px 8px 10px 16px; position: relative; border: ridge 10px #87CEFA; } .mask { width: 100%; height: 100%; position: absolute; top: -100%; /* 枠の上に配置し非表示にする。 */ opacity: 0; /* マスクスクラス内を透明化(0)にすることで非表示にする。*/ background-color: rgba(0,0,0,0.4); transition: all 0.6s ease; } .caption { font-size: 130%; text-align: center; color: #fff; } img.alabumImage { width: 80%; height: 80%; position: absolute; } .album:hover .mask { アルバムクラス内をhover(カーソルを乗せる)時に発火する。 opacity: 1; /* マスクを完全に不透明表示にする */ padding-top: 80px; /* ホバーで下にずらす */ top: 0; /* 先ほどのtop: -100% から top: 0;にすることにより下から降りてくるように見せることができる */ }
完成!!!
デモンストレーション
![]()
詳細な動き
form内にアーティスト(曲名も可)を入力し検索ボタンをクリックすることでitunesapiからアーティストが発売したアルバムを取得し、表示しています。
今回のmusic.js, music.cssの全コード
(※artistdata.js
は上記のコードが全コードです。)music.jsimport React, {useState } from 'react'; import axios from 'axios'; import ArtistData from './artistdata.js'; import '../styles/music.css' const Music = () => { const [artist, setArtist] = useState(''); const [artistData, setArtistData] = useState([{ CollectionId: '', ArtistName: '', AlbumName: '', AlbumUrl: '', AlbumGenre: '', AlbumRelease: '', }]); async function itunesGet(params){ try{ const prm = params.trim(); const response = await axios.get(`https://itunes.apple.com/search?term=${prm}&entity=album`) const responsedata = response.data.results const responseAPI = responsedata.map(value => { return { CollectionId: value.collectionId, ArtistName: value.artistName, AlbumName: value.collectionName, AlbumUrl: value.artworkUrl100, AlbumGenre: value.primaryGenreName, AlbumRelease: value.releaseDate, }; } ); setArtistData(responseAPI); console.log(artistData); }catch(error) { const { status, statusText } = error.response; console.log(`Error! HTTP Status: ${status} ${statusText}`) } }; return ( <div> <form onSubmit = {e => { e.preventDefault(); const artistnameElement = e.target.elements["artist"]; console.log(artistnameElement.value); itunesGet(artistnameElement.value); setArtist(artistnameElement.value); artistnameElement.value = ''; }} > <input type="text" id="artist" placeholder="アーティスト名または曲名を入力してください" /> <button type="submit">検索する</button> </form> <p className="result">検索結果: <b>{artist}</b></p> <div className="searchresult"> {artistData.map(artistdata => ( <ArtistData key={artistdata.CollectionId.toString()} id={artistdata.CollectionId} name={artistdata.ArtistName} album={artistdata.AlbumName} albumUrl={artistdata.AlbumUrl} genre={artistdata.AlbumGenre} release={artistdata.AlbumRelease} /> ) )} </div> </div> ) } export default Musicmusic.css* { margin: 0 auto; padding: 0; box-sizing: border-box; } form > :first-child { outline: none; border: 1px solid #aaa; transition: all .3s; border-radius: 2px; } form > :first-child { width: 400px; font-size: 18px; height: 24px; padding: 2px 8px; } form > :nth-child(1):focus { box-shadow: 0 0 7px #1abc9c; border: 1px solid #1abc9c; } form > :last-child { margin-top: 4px; margin-left: 7px; font-size: 16px; height: 40px; padding: 2px 8px; } form button { border: 1px solid #ccc; background-color: #FFFFFF; border-radius: 2px; cursor: pointer; box-shadow: 0px 2px 2px 0px rgba(0,0,0,.1); } form button:hover { box-shadow: 0px 2px 2px 2px rgba(0, 0, 0, .1); } .result { text-align: center; } .searchresult { display: flex; flex-wrap: wrap; justify-content: space-around; } .noalbum{ display: none; } .flex { padding: 3px 1px; display: flex; flex-direction: row; } .flex > :nth-child(2) { padding-top: 1.7em; padding-bottom: 0.5em; } .flex > :nth-child(2):nth-child(2){ font-family: 'Courier New', Courier, monospace; } .album { width: 300px; height: 230px; overflow: hidden; margin: 10px 8px 10px 16px; position: relative; border: ridge 10px #87CEFA; } .mask { width: 100%; height: 100%; position: absolute; top: -100%; opacity: 0; /* マスクにする */ background-color: rgba(0,0,0,0.4); transition: all 0.6s ease; } .caption { font-size: 130%; text-align: center; color: #fff; } img.alabumImage { width: 80%; height: 80%; position: absolute; } .album:hover .mask { opacity: 1; /* マスクを完全に不透明表示する */ padding-top: 80px; /* ホバーで下にずらす */ top: 0; }まとめ
- 「このサイト、アプリはどのように実装されているのだろうか?」と疑問を持ち実際に自分で実装することで自分の技術力UPに繋がるということを改めて知ることができたそんな師走上旬でした。。。
裏話
FNS公式HPのデベロッパーツールのSourceパネルと睨めっこしながら実装したのは内緒。。。
参考資料