More Channels
Showcase
Articles on this Page
- 11/01/19--04:50: _🀄上海のクリア可能パターン生成
- 11/01/19--07:43: _HTML付近のあれこれ
- 11/01/19--22:17: _CSSセレクタの優先順位
- 11/02/19--02:42: _コンテンツが下からスクロールで表示され...
- 11/02/19--09:20: _自分用
- 11/03/19--02:28: _年末まで毎日webサイトを作り続ける大...
- 11/03/19--05:25: _flexboxの基本的な使い方
- 11/03/19--07:10: _borderを使用した三角形(吹き出し...
- 11/03/19--07:36: _[メモ]border-radiusの使い方
- 11/03/19--23:40: _Webプログラミングの勉強を始めて約半...
- 11/04/19--01:00: _【Qiita】記事で画像を横並びにする
- 11/03/19--20:59: _jQueryで複数のスライドダウンコン...
- 11/04/19--00:19: _firebase ポートフォリオサイト...
- 11/04/19--00:19: _z-indexがautoと0とで重ね合...
- 11/04/19--05:03: _【ASP.NET Core MVC】A...
- 11/05/19--02:29: _【保存版】Webフロントエンド基礎力(...
- 11/04/19--19:04: _Vue.jsでじゃんけんゲーム作りました
- 11/04/19--19:36: _float の解除 clearfix
- 11/05/19--01:24: _webプログラミングってなに?始めるた...
- 11/04/19--22:51: _HTML CSS 【パンくずリスト】っ...
Channel Description:
- 左右少なくとも一方に隣接する牌が無く、
- 上に別な牌が積み重なっていない、
- 同じ柄の牌の組
- 左右少なくとも一方に隣接する牌が無く、上に別な牌が積み重なっていない牌
- 積み上げられた麻雀牌の山から、同じ柄の自由牌の組を取り除いて行き、全て取り切ったらクリアというパズルゲーム
- マウスクリックで選択
- 全部消せたら clear
- これ以上取ることができない状態(詰み)になったら game over と表示されます。
- 各種ボタン
- Undo: 一手戻る
- Reset: 最初に戻る
- New: 新規問題を生成
- 生成される問題は、解答が一つ以上存在します。
- 同じ柄である
- どちらも自由牌である
- 一つ目は最も高いもの
- 二つ目はランダム
- 上海のサンプルと基本的な作り方を解説しました。コード解説はサボった。
- 適当に盤面作るとまともに遊べないぞ!気をつけろ!
- 事前に盤面作ってもいいけど、楽したいよね。
- 無地上海使うと盤面生成できるぞ!
- 無地上海にも詰みがあるぞ!
- 詰みルート回避しよう!
- 回避できた!
- でもショートコーディングに向かない。悲しい。
- シャンハーイ
- static
- 初期値。
- fixed
- 画面の決まった位置に固定。
- absolute
- 親要素を基準に絶対的な位置を決定。
- relative
- 現在の位置を基準に相対的な位置を決定。
- 画像の上にテキスト,別の画像を重ねておきたいとき。
- 何かの操作手順。
- パンくずリスト。
- グローバルナビゲーション。
- ローカルナビゲーション。
- 順序関係なく列挙したい項目。
- 例えば,注意事項。
- 入力フォーム。
- 例えば,問い合わせフォーム。
- px
- ブラウザや端末に依存せず,フォントサイズを指定できる。
- %
- 親タグのフォントサイズと比較したときのサイズを指定できる。
- em
- %と同じ意味。
- 書き方が違うだけ。1emは100%と同じ意味。
- rem
- 基準としているものが,ルート要素。
- あんまり使わない印象。
- 塗りつぶしの多い画像(イラスト系など)はPNG。
- 複雑な画像(写真系など)はJPEG。
- Webページ全体の文字に対してまとめて適用するため,bodyをセレクタとして指定する。
- ブラウザ依存で,文字などの位置が変わらないように両方0に指定する。
- HTMLタグは,ボックスで成り立っており,content, padding, border, marginの4構成。
- paddigはボックス内で位置調整のために使用。
- marginはボックス間の位置調整のために使用。
- CSSはケバフケースで記述(これについては賛否ありそう)。
- 要素のまとまりごとにつける。
- header, main, section, aside, footerなど。
- HTML5で追加。
- 使用することで,検索エンジンに正しく内容を認識してもらえる。
- HTML5以前は,divにidを指定して記述していた。
- 例えば,
<main></main>
は,<div id="main"></div>
と記述されていた。
- 例えば,
- ブラウザによっては適用されない場合がある。
- IE8以下は適用していない。
- 逆に言えば,特定のブラウザ(IE8以下など)に適用させるために,divを使用する場合もある(たぶんもうないと思うけど)。
- メディアクエリ(@media)でサイズに応じたデザインを作成。
- メディアクエリで場合分けした分,CSSのコード量が増える。
- ブレイクポイントはいろいろあるらしい。2019年は560px/960px?
- 560px未満はスマホ,960px未満はタブレット,960px以上はPC。
- 基本的に,headタグのtitleタグ下に記述する。
- 全要素をCSSの対象範囲とする
* { }
のような書き方は避ける。 - bodyタグ内の一番下に記述。
- headタグ→bodyタグの順に読み込まれるため,headタグに記述するとぺージが表示されるまでに時間がかかってしまう。
- Google Analyticsなどの解析に関するものは,head内に記述。
- bodyタグに記述してしまうと,JavaScriptのコードが実行される前に,ユーザーがページから離れてしまう可能性がある。
Chrome デバッカーツール
- Windowsなら
F12
,MacならCommand+Option+I
で呼び出せる。 - スマホやタブレットのエミュレート機能が便利!
- Windowsなら
ColorPick Eyedropper
- Chromeの拡張機能。
- ブラウザ上に表示されているものの色を調べられる。
- HTML5&CSS3 デザインブック(ソシム)
- 世界一わかりやすいHTML5&CSS3コーディングとサイト制作の教科書(技術評論社)
- 現場のプロから学ぶ SEO技術バイブル(マイナビ)
- オリジナルスタイリング側でも
!important
句を使う - フレームワークを採用しない
- フレームワークを(CDNではなくダウンロードして使うことを前提に)改造し、
!important
の記述を取り除く - フレームワークのスタイリングに従い、オリジナルのスタイリングを諦める
- レスポンシブなメニューの表示変更の方法
- 動画の挿入方法と注意点
- JavaScriptを用いて要素を作る
- Free Stock Video Footage HD Royalty-Free Videos Download (https://mazwai.com/#/grid)
- integer
- This integer is the stack level of the generated box in the current stacking context. The box also establishes a new stacking context.
- auto
- The stack level of the generated box in the current stacking context is 0. The box does not establish a new stacking context unless it is the root element.
- root要素(背景黒
#2d2d2d
)は、root stacking contextを形成する。 - 各boxはどれか1つの重ね合わせコンテキストに所属する。
- 黒
#2d2d2d
の背景が机の表面 - 書類AとBがあり、それぞれ3枚付箋を貼ってある
- 書類の表面に付箋用の「重ね合わせコンテキスト」が形成される
- 付箋にはstack levelが割り当てられ、その書類に貼られる付箋どうしの重なり順を決めている
- 書類にもstack levelが割り当てられ、机に書類を重ねて置く時の重なり順を決めている
- c2
#fff9a5
のstack level=-200が比較される対象は、Bが生成した重ね合わせコンテキスト内の要素c1, c2, c3のstack level。結果、それらの中で最小値を持つc2がスタックの最下位に描画される。 - Bのstack level=100が比較される対象は、Bが所属する重ね合わせコンテキスト内の要素(Aや、Aのc2)のstack level。親要素と子要素のz-indexを比較しても意味がない。
- Aのc1
#b0cdeb
, c3#f9b8bc
のz-index値をいくら大きくしても、重ね順はBとその子要素より上にならない。stack levelは重ね合わせコンテキストをまたがって比較されない。 - Aのz-indexをautoから整数値に変えると、Aのc2
#fff9a5
がAの裏側から前面に移動する。Aが新たに重ね合わせコンテキストを生成したため、c2のz-indexはそちらのコンテキスト内でのstack levelになる。 - html: HTMLページであることを示すタグ
- title: ページのタイトルを記述するためのタグ
- meta: ページのメタ情報を記述するためのタグ
- head: ページのヘッダー部分を記述するためのタグ
- body: ページのボディ(メイン)部分を記述するためのタグ
- div: ブロックの塊を示します、レイアウトを組むときに主に使います。
- ol: 順序ありリスト
- ul: 順序なしリスト
- details, summary, dl: 展開式の要素です。summaryに展開するタイトル、dlに展開する子要素を記述します。
- table, tbody, th, tr, td: テーブル要素、thに見出し、tr単位に行作成、tdに内容を記述します。
- h1, h2, h3, h4, h5, h6: 見出し要素、h1, h2...の数字が大きくなるにつれて見出しが小さくなります。
- p: パラグラフ、文章を記載します。
- span: デザイン微調整によく利用されるタグ(インライン要素)
- form: フォーム要素。ユーザに入力してもらったデータをサーバに送信する用途で使います。
- label: ラベル要素。フォーム要素の中で使われることが多いです。
- input: 入力欄要素。フォーム要素の中で使われることが多いです。
- button: ボタン要素。ユーザインタラクティブのトリガーとして使われます。
- a: ハイパーリンク要素。別ページへのリンクやページ内リンク(アンカーリンク)として使われます。
- img: イメージ要素
- audio: 音声プレイヤー要素
- video: 動画プレイヤー要素
- canvas: 2D、3Dのグラフィックを描画するための領域
- style: スタイル要素(CSS等)
- script: スクリプト要素(JavaScript等)
- text: 1行テキスト
- email: メールアドレス
- password: パスワード
- radio: ラジオボタン
- checkbox: チェックボックス
- range: スライダー
- number: スピナー
- color: カラーパレット
- date: 日付
- time: 時間
- file: ファイル
- hidden: 隠しパラメータ(入力欄としては表示しないがサーバに送信するパラメータ。value属性と併用することが普通でCSRF対策に主に使う)
- submit: 送信ボタン
- 表示のパフォーマンスが落ちる(重複している無駄なスタイルを削除する方を優先したほうが良い)
- そもそもidやclassで代用できるはず
- !importantで書いてしまうと後勝ちの!importantでしか上書きできなくなる(このため、優先順位がわからなくなりCSSの修正が困難になる)
- brightness: 明度
- contrast: コントラスト
- grayscale:グレースケール
- saturate: 彩度
- sepia: セピア
- hue-rotate: 色相
- invert: 色相反転(ネガポジ)
- blur: ぼかし
- opacity: 透明度
- drop-shadow: 影
- -moz-:Firefox
- -webkit-:Google Chrome、Safari
- -o-:Opera
- -ms-:Internet Explorer
- CSSファイルのMinify化:CSSファイルに分離し、CSSファイル自体をMinify(圧縮&難読化)する
- セレクタを見直す
- 似通ったmargin,paddingや色コードをまとめる
- 重複しているスタイルを削除する
- ブラウザのレンダリングの仕組みに関して理解を深める
- babel、webpack、Parcelの知識を深める(参考:webpackとBabelの基本を理解する(1) ―webpack編―)
- JavaScriptフレームワークを使ってみる(個人的にはReactがおすすめ。参考:ReactJSで作る今時のSPA入門(基本編))
- TypeScriptの勉強をする、JavaScriptフレームワークにTypeScriptを導入してみる(参考:TypeScript練習帳(入門))
🀄上海🀄
「上海」とは、積み上げられた麻雀牌の山から、
を取り除いて行き、すべて取り除いたらクリアというパズルゲームです。
基本的には 144枚(数牌+字牌+花牌+季節牌)の牌を使いますが、難易度や盤面設定により様々なバリエーションがあります。牌の積み方も色々。
上海の指南書や攻略サイトなどでは、
のことを、自由牌と呼ぶようです。
この定義を使って言い換えれば、「上海」は、
ということになります。
サンプル: とりあえず遊んでみよう
See the Pen Shanghai by nagtkk (@nagtkk) on CodePen.
本題
前回、四川省をやったのでその流れで上海、なんですけど、
上海は真面目に作ろうとすると結構難しい。
コード自体は割とシンプルに収まるのですが、盤面の生成周りが色々と大変。
少なくとも初心者向きとは言い難い。
と言うわけで、前回と異なり実装例の紹介まで行きません。
基礎部分の作り方と盤面生成の話をメインにしようかと思います。
サンプルの中身が見たい方は CodePen からどうぞ。
描画部分は相変わらず手抜き気味ですが。
あとは四川省でやったショートコーディングも無しです。
上海は色々と理由があって向かないと思っているので。
基礎部分: 盤面状態の表現と自由牌判定
さて、上海を作るには、まず麻雀牌の山をデータとして表現する必要があります。
上海で用いられる麻雀牌の山は、山と言うくらいですから3次元です。
また、単に並んでいるだけではなく牌を縦横「半分ずらして」配置することができます。
やり方は一通りではありませんが、今回は「縦横二倍の密度の盤面」を高さ毎に用意し、
4マスセットで一つの牌を表現することにします。
こうしておけば、「半分ずらし」も問題なく表現できます。
「隣の牌」は、データ上「2マス」離れていることになります。
この形式のデータで自由牌か否かを判定するには、判定対象の座標を (x,y,z)
とすると、以下の領域に他の牌があるかを判定すれば良いことになります。
柄の判定は、柄 ID でも付けて比較すればよいので略。
これで実行に必要なものは一通りそろいました。
選択された二つの牌が、
ならば、取り除くだけです。
いやあ楽ちん楽ちん、
とならないところが上海の怖いところ。
乱数による盤面生成の問題点
前回の「四川省」も、今回の「上海」も、単に乱数のみで盤面を生成すると、最初から詰んでる(クリア不能)パターンが発生することがあります。
四川省の時は、実装例では「内部的に一度手当たり次第に解いてみて、解けなかったら再生成」としていました。
ショートコーディング版ではそれすらさぼって、「詰んでたらプレイヤーがリロードしてね」と雑な対処をしていました。
「四川省」は、そもそも初期状態で詰んでいる可能性が低いので、こんなんでも割と遊べてしまいます。
が、「上海」ではそうもいきません。乱数頼りで盤面生成すると、最初から詰んでいるケースが多いのです。
どのくらい詰みやすいかは、牌の積み方で変わってきますが、今回使った積み方 TURTLE (サン電子版では「龍」)では、50個生成して全部クリア不能みたいなことも起こります。
何らかの対処をしないと「普通に遊べる」状態になりません。
一つのやり方は、盤面をランダムに生成しコンピュータに解かせるプログラムを書いてしまう方法です。
実際に解けたもののみ採用すれば、最初から詰んでいる状態は回避できます。
時間がかかるので、実行時にやるのではなく、事前に作りためて実行時には単にロードするだけ。
ついでに難易度のラベリングなんかもしておけば、ゲームの幅が広がります。
(自動で難易度判定するのは、それはそれで別方向で難しい話ですが)
あるいは、製作者が解いてみて解けたやつを記録するとか、手作業で盤面作るとかいう手もありかもしれません。(大変そう)
今回は別なアプローチで、「必ず一つ以上解が存在する」ように上海の盤面を自動生成する方法を解説しようかと思います。
無地上海を利用した盤面生成
無地上海、という名前は今適当に決めました。
要は「柄のない」(あるいは「柄がすべて同じな」)上海のことです。
柄が無いので、自由牌ならどれでも組にできます。
生成したい普通の上海と同じ牌の積み方で無地上海を作り、自由牌からランダムに組を作って取り除いて行きます。
このとき、取った牌の組を元の位置も含めて覚えておきます。
そして、解いた後に実際に組(ペア)になった牌に後付けで柄を決め、元の形になるように積みなおします。
こうして出来上がった上海は、無地上海と同じ手順で解くことができます。
つまり、解が一つ以上存在する、を満たせたわけですね。
上海に限らず、パズルゲームでは「制約緩めて解いてしまって後付けで都合のいい条件を追加する」やり方がいろんな場面で役に立ったりします。自作のパズルゲーム作るときとか。
閑話休題。
これで詰んでない上海が作れた、
と言いたいところですが、これでも上手くいかないのが上海の怖いところ。(二回目)
無地上海にも解いている最中に「詰み」が発生する可能性があるので、完全ランダムではなく、詰みを回避するように解く必要があります。
無地上海の詰む・詰まない
柄のない上海が詰むのは「組が作れない」つまり「自由牌が一つしかない」ためです。
例えば以下のようなケース。
最終的に自由牌が 1 になって詰みます。
これらはあくまで一例で、他にも色々と自由牌 1 に至るパターンがあります。
「自由牌が 1 になったその時に詰んでいる」のではない点にご注意ください。
その前段階から、回避手段が存在しないので既に詰んでいます。
つまり、詰み回避のためには、「最終的に自由牌が 1 になるルート」に突入しないことが必要です。
逆に、詰み回避できているパターンも見てみましょう。
上は、「取り方によっては詰むけれど、順番を間違えなければ詰まない」ケース。
下は、「どうあがいても詰まない」ケースです。
これらは詰むパターンと一体何が違うのか、というのを厳密にやりだすとひたすら長くなるので、十分条件で抑え込んでしまいましょう。
$$ {\rm 最も高い自由牌の高さ} - {\rm 二番目に高い自由牌の高さ} \lt {\rm 自由牌の個数}$$
の時、まだ詰んでいません。そうでない場合、詰んでいる可能性があります。
とりあえず詰み回避条件とでも呼びましょうか。
よくわからんと言う人は、上の図と見比べてみるとわかりやすいかも。
要は、「自由牌 1 」の状態は「高低差を埋めるために必要な自由牌が足りない」時に発生するので、高低差が開きすぎちゃうと取り方工夫しても挽回できなくなるかもよ、ということですね。
初期状態で詰み回避条件に合致していれば、この条件を維持するように取ることで、無地上海は詰まずに解ききることが可能です。
この方法は、十分条件で縛っているので、本来詰まないパターンも一部回避してしまっている(理論的に生成可能なパターンをすべて網羅はできない)ことになります。
実用上十分だろうと思いますが、一手間違えただけで即詰むようなスリルのある上海がやりたい、という場合には、この方法は適していません。
また「高さがある牌の下面には他の牌がある」という前提での話ですので、変則的な上海には適用できませんのでご注意を。
コーナーケース
今回の TURTLE では起こらない話ですが、牌の積み方によっては、実際には解けるけど初期状態で詰み回避条件に合致していない、と言うケースもあります。
その場合は、条件を満たすまで「最も高い自由牌を含む組」を取っていきます。
進めていくと、高低差が維持あるいは減少し、解が存在するならばいずれ条件を満たすようになります。
もし詰み回避条件を満たさないまま詰んでしまった場合。
その牌の積み方には、そもそも解が存在しません。
普通の上海としてもクリアパターンが存在しないことになります。
ちなみに、組の両方とも常に高いものから取っていくという方法でも、解が存在する場合には無地上海を解ききることができます。
ただし最終的に出来上がる上海は、とりあえず上から取っていけばクリアできるイージーモードになります。
ミニゲームとかはそれでもいいのかも。
詰み回避条件の維持
今回サンプルで使った方法は、基本的にはランダムに自由牌の組を選びますが、
$$ {\rm 最も高い自由牌の高さ} - {\rm 二番目に高い自由牌の高さ} + 2 \ge {\rm 自由牌の個数}$$
の時は、取り除く牌を、
にする、というものです。
詰みルートに突入する可能性があるときに、片方を最も高いものから取ることで高低差が開かない(=詰み回避条件を維持する)ようにしています。
コーナーケースの場合にも、最も高い自由牌を含んだ組が選ばれます。
詰む危険性がない時には単にランダムに取っていくので、常に簡単になってしまうという心配はあまりありません。
さて、これで詰まずに無地上海が解けるようになったので、前述の方法で解が一つ以上存在する上海のパターンが作れます。
おつかれさま!
おまけ: 麻雀牌
スタイルシートでごり押し。
若干おかしいけど、まあ、黙ってりゃバレないバレない。
See the Pen Mahjong Tile by nagtkk (@nagtkk) on CodePen.
余談: なぜショートコーディングに向かないのか
一つには、ここまで散々述べてきたように、詰みパターンの回避を入れないとそもそも遊べる状態になりにくいからです。
ショートコーディング的には、その手のものを省いてでも短さを追求する方が「ぽい」と思うのですが、遊べないものを作ってもなあ、と色々と悩みどころ。
で、二つ目に「牌の積み方」が大半を占めてしまうから、というのがあります。
今回のサンプルでは、積み方データは牌の有無を表す 0 or 1の 配列で 32 * 17 * 5 = 2720 要素あります。でかい。
牌は144個しかないので、座標で持つようにすれば 144 要素にできますが、それでもまだでかい。
牌の有無を一行まとめて 32 ビットの整数として扱えば、17 * 5 = 85 要素。一要素当たりのコードが長くなるので効果はいまいち。
で、ここから短くしようと考えると、ランレングスかハフマンか、いや事前に要素間の差分を取ったほうが……それもうショートコーディングっていうかデータ圧縮の話だよね?
面白さが無いとは思いませんが、どんどん別物になってくるので、個人的にはショートコーディングには向いてないなあという結論に至りました。
上海自体は面白いんですけどね。
まとめ
HTML付近のあれこれ
HTMLやCSSなどの勉強していて,「あれ?これどうするんだっけ」と思ったところがあった。そういうものをメモ程度にまとめていく。
目次
HTMLとCSS
1. position
2. ol, ul, dl
3. px, %, em, rem
4. PNG, JPEG
5. font-family
6. margin, padding
7. float
8. 命名規則
SEO対策
1. div, 構造化タグ
2. レスポンシブ
3. JavaScriptやCSSをHTMLから呼び出す
ツール
参考
HTMLとCSS
1. position
positionのプロパティ
よく使うのは,absoluteとrelativeの2つ。
absoluteとrelativeの用途
2. ol, ul, dl
リストと聞いたら,この3つが思い浮かぶ。
ol(ordered listの略)の用途
ul(unordered listの略)の用途
dl(definition listの略)
<!--問い合わせフォームで使用する例-->
<dl>
<dt>氏名<dt>
<dd>kotti</dd>
</dl>
この3つは略称ではなく,正式名称で覚えておくと,どれを使ったらいいかすぐに思い出せるかも。
3. px, %, em, rem
サイズの絶対指定
サイズの相対指定
4. PNG, JPEG
5. font-family
6. margin, padding
h1を例にするなら,下記のように書く。
h1 {
margin: 0;
padding: 0;
}
7. float
<!Doctype html><htmllang="ja"><head><metacharset="utf-8"><title>position</title><linkrel="stylesheet"type="text/css"href="test.css"></head><body><divclass="box1"><p>box1</p></div><divclass="box2"><p>box2</p></div><divclass="box3"><p>box3</p></div><divclass="box4"><p>box4</p></div></body></html>
test.cssは,test.htmlと同階層に保存。
@charset"UTF-8";.box1{background:red;}.box2{background:blue;}.box3{background:green;}.box4{background:pink;}
box2とbox3を横並びにするために,float
を使う。
具体的に,下記のように記述(変更した箇所のみ記述)。
<!--box2とbox3を横並びにする--><divclass="box"><divclass="box2"><p>box2</p></div><divclass="box3"><p>box3</p></div></div><!--/box2とbox3を横並びにする-->
.box::after{content:"";display:block;clear:both;}.box2{background:blue;float:left;width:50%;}.box3{background:green;float:right;width:50%;}
これを応用すれば,Webページのレイアウトが簡単に調整できる。
ちなみに,これを使えば,リストを横並びにもできる。
<body><divclass="menu"><ul><li><ahref="#">トップ</a></li><li><ahref="#">会社案内</a></li><li><ahref="#">問い合わせ</a></li></ul></div></body>
@charset"UTF-8";.menuul{margin:0;padding:0;list-style:none;}.menulia{display:block;padding:5px;color:#000000;text-decoration:none;}.menulia:hover{background-color:#eeeeee;}.menuul::after{content:"";display:block;clear:both;}.menuli{float:left;}
8. 命名規則
ちなみに,7. floatで,クラス名をbox1などとしてたけど,あれは具体例として雑につけたやつ。
本来は,〇〇-boxとか,〇〇-blockとかにした方がいいのではと思う。
SEO対策
SEOとはSearch Engine Optimizationの略で,検索エンジンの最適化という意味。
1. div, 構造化タグ
div
構造化タグ
2. レスポンシブ
3. JavaScriptやCSSをHTMLから呼び出す
CSSの場合
JavaScriptの場合
ツール
使用しているツール
参考
1. Webサイト
[1] CSSのpositionを総まとめ!absoluteやfixedの使い方は?
[2] CSSでのサイズ指定はどれがいい?「px」「%」「em」「rem」の違い
[3] PNGとJPEGどっちがいいのか?「画像のベストな保存形式」
[4] font-familyの書き方まとめ:CSSでフォント種類を指定しよう
[5] CSSのmarginとpaddingを使い分けるための4つのポイントを紹介! 違いについても理解しよう
[6]レスポンシブデザインのブレイクポイントの正解はこれだった[2019最新版]
[7] HTMLとCSSクラスでよく使う命名について
[8] CSSのクラス名を決めるときに使うリストをつくりました
2. 書籍
はじめに
CSSやBootstrapを使用していてよくあるデザインが反映されない問題について、文法間違いやパスの指定など色々な原因がありますが、CSSセレクタの優先順位が関係していることがよくあるのでまとめます。
CSSの優先度
CSSの記述がうまく反映されないとき、文法の間違いもなく、パスの指定も問題ないという場合はより優先度の高いCSSがどこかに記述されている可能性が高いということです。
またBootstrapなどのフレームワークを採用していたら、!important
句でスタイルを強制されている可能性が高いです。
CSSは複数箇所で同じタグに対し、競合した内容を書けてしまいます。
例えば以下のように。
p{color:red;}p{color:blue;}
この場合、pタグのスタイリングはどうなるのでしょうか。
CSSには、競合するスタイリングをしたときにどのスタイリングが採用されるかの基準である「優先度」が存在します。
CSSは(同じ詳細度なら)より後ろに記述したスタイリングを適用するので、color:blue
が適用されます。
次に位置によらない「タグへのセレクタの指定の度合いの詳しさ」である「詳細度」が関係します。
全称セレクタ<タイプセレクタ<クラスだけ<クラスと要素<id<idと要素<!importantを付加したプロパティ
の順で、右に行くほど詳細度は高くなっていき、最も詳細度の高いスタイリングが適用されます。
CSSを以下のようにしたとき
/*要素を特定したidセレクタ*/p#hoge{color:red;}/*要素を特定しないidセレクタ*/#hoge{color:blue;}/*要素を特定したclassセレクタ*/p.fuga{color:yellow;}/*要素を特定しないclassセレクタ*/.fuga{color:green;}/*タイプセレクタ*/p{color:orange;}/*全称セレクタ*/*{color:purple;}
<!-- p要素にはid属性とclass属性を同時に指定する --><pid="hoge"class="fuga">何色になる?</p>
HTMLの文字色は、最も詳細度の高い「idと要素」のスタイリングである赤色が適用されます。
なお、前述の通り同じ詳細度のセレクタ同士ならCSSファイルのより後ろに書いたものが、またHTML内で後に読み込んだものが優先されます。
よって、質問のような状況では「より詳細度の高い指定が既に他の場所に記述されてしまっている」ことがまず考えられるので、タグに適用されているCSSを全て確認してみましょう。
タグに適用されているスタイリングは、Chromeブラウザならコンソール画面→Stylesメニューから確認できます。
!important
!important
句は、セレクタの詳細度や位置に関わらず「プロパティを最優先で変更する」命令です。
以下のように詳細度の最も低い全称セレクタに書いたプロパティでさえ、最優先で適用させることができてしまいます。
*{color:black!important;}
!important句とフレームワーク
もしサイトにBootstrapやMaterializeなどのCSSフレームワークを採用している場合には、オリジナルスタイルの扱いが難しくなります。
なぜならこういったフレームワークは、「フレームワーク側のソースコードでスタイルを!important
句を用いて固定している」ことが多いためです。
こちら側から通常の方法で競合するスタイリングをしていては、フレームワーク側のスタイリングが優先されてしまいます。
解決策としては
方法があります。
2や4が初学者向きの解決策ですが、どうしてもフレームワークとオリジナルスタイルを共存させたいのであれば1または3を検討しましょう。
参考
この記事は「CodeShip」内での実際の質疑応答や指導・アドバイスの一部を基に作成しています。
コンテンツが人画面に収まりつつ、スクロールすると次のコンテンツが表示されるプラグインです。
デモページ
デモページ
HTMLのclass="section"ごとに下からズズッと表示される感じです。
コンテンツがウインドウサイズより長くても大丈夫
一つのコンテンツがウインドウサイズより長くてもスクロールで見れるようにしたかったのでそのようになっています。内容量を気にしません。
コンテンツ量が少ないとウインドウ幅いっぱいに要素が広がるようになっています。
実行方法
$('#wrap').scrollContent();
wrapの箇所をスクロール表示したい親要素を指定します。
スクロールバーを非表示にしたい
前途の理由で移動の際にもスクロールバーが出ます。このスクロールバーがない方がいい時は以下のように実行します。
$('#wrap').scrollContent({type:'noBar'});
ナビゲーションのclass(id)を変えたい
ナビにつかうclassを変えたい時もあるかなと思い、オプションでナビゲーションのclass(id)を変更できます。指定しないと.navが適用されます。
$('#wrap').scrollContent({nav:'.nav'});
ダウンロード
ダウンロードはこちらら
webdrawer-kashu/contentScroll
この記事の転載元
コンテンツが下からスクロールで表示されるjQueryプラグイン|WEB Drawer|web制作に関するネタの引き出しサイト
bootstrapのサイトにアクセスする。
Bootstrapを、そのまま使用するのなら、CDNをコピーするだけで使える。
style.cssを読み込む、直前の部分に貼り付ける。(link rel="stylesheet" href="css/style.css")
htmlに、決められたタグを入れることでBootstrapが勝手に調整してくれる。
body
div class="container"
header...
/div
/body
//全体を,div class="container"で囲む。//
グリッドシステム
div class="row"
//class名はrow//
div class="col-○○-1~12
//colはカラム、○の部分はxs,sm,md,lg、数字は使うカラムの数//
はじめに
こんにちは!
年末まで毎日webサイトを作っている者です。
今日はゆくゆくwebサイト制作でお金をもらうための練習ということで、Ap●leのファーストビューをソースコードを見ずに動きを見て模倣してみました。(fontだけはソースみました)
扱う技術レベルは低いですが、同じように悩んでる初心者の方を勇気付けられれば幸いです。
今日は16日目。(2019/11/3)
よろしくお願いします。
サイトURL
https://sin2cos21.github.io/day16.html
やったこと
Ap●leのファーストビューを真似してみました。
まずは結果からどうぞ (gif)↓
以下順番に説明していきます。
1. レスポンシブなメニューの表示変更の方法
ちょうどheaderのメニューの数が変わるのが767pxと768pxでした。
なのでまずはcssのメディアクエリで大きさによってスタイルを変更します。
/* ↓これでサイズごとにメニューの数を変更する */@mediascreenand(max-width:767px){#width767px{display:flex;justify-content:space-around;min-width:320px;width:100%;}.headerItem1{/* ↓メニューの切り替えはこれで行う */display:none;}}@mediascreenand(min-width:768px){#width_1000px{display:flex;justify-content:space-around;min-width:768px;max-width:1000px;width:100%;}.headerItem2{/* ↓メニューの切り替えはこれで行う */display:none;}}
あらかじめふた通りのdomとデザインを用意しておいて、あるpx以上ならこっちを消す、違う時はこっちを消すということをdisplayのnoneで実現しています。
2. 動画の挿入方法と注意点
次に動画の挿入ですが、これは基本的にhtmlで書きます。全体に表示したいなど細かいところはcssの出番です。
html ↓
<videoid="first_video"mutedautoplayloop><sourcesrc="sample1.mp4"></video>
#first_video{/* ↓固定する */position:fixed;right:0;bottom:0;min-width:100%;min-height:100%;width:auto;height:auto;/* ↓headerを隠さないようにz-indexを指定する */z-index:-100;/* ↓画面全体に表示されるようにする */background-size:cover;}
htmlの方で1つ注意点があります。属性にmutedを入れないと動画が自動再生されなくなるので、自動再生したいなら必ず入れましょう。(ちなみにmutedと全く関係ないですが、sourceタグを使わずvideoタグ内にsrc属性を書こうとして30分ぐらい奮闘しました。srcをvideoに直接書いたらダメなんですね・・・)
3. JavaScriptを用いて要素を作る
これはおまけというか、必ずしもしなくていいですが、将来を見越してスクリプトからDOMをいじる練習をしました。
window.onload=function(){letwidth_1000px=document.getElementById('width_1000px');letwidth767px=document.getElementById('width767px');lettext=['#ロゴ','Mac','iPad','iPhone','Watch','TV','Music','サポート','#検索','#バッグ'];lettext2=['#メニュ','#ロゴ','バッグ'];for(vari=0;10>i;i++){varheaderItem=document.createElement('div');varheaderItemText=document.createTextNode(text[i]);console.log(headerItemText);headerItem.appendChild(headerItemText);headerItem.setAttribute('class','headerItem headerItem1');width_1000px.appendChild(headerItem);}for(vari=0;3>i;i++){varheaderItem=document.createElement('div');varheaderItemText=document.createTextNode(text2[i]);headerItem.appendChild(headerItemText);headerItem.setAttribute('class','headerItem headerItem2');width767px.appendChild(headerItem);}}
サイズごとに2パターンの要素を作るように書いています。
長いのでもうちょっと簡単に書けそうですね。(というか他に方法がある気がする)
感想
今日は外見だけ真似をして動作までは実装していません。だからサイズが小さくなった時にハンバーガーメニューを押してもメニューは出てきません。サイトを作るのはなかなか大変だなぁと思いつつも、実際に目に見える形になると嬉しいですね。
最後までお読みいただきありがとうございます。明日も投稿しますのでよろしくお願いします。
参考
動画使わせていただきました。ありがとうございます!
しっかりしたCSSの理解が不足していたので要素の横並びにfloatや管理画面等ではBootstrapのグリッドレイアウトに頼っていたため流行りのflexboxの概要を確認してみた内容の覚え書き。
親要素よりも大きい子要素を10個準備
親の枠を超えた10個のdivタグを用意してわかりやすくするために色をつける
<!DOCTYPE html><htmllang="ja"><head><metacharset="UTF-8"><linkrel="stylesheet"href="style.css"><title>flexbox</title></head><body><divclass="container">//親要素
//子要素10個
<divclass="sample1">1</div><divclass="sample2">2</div><divclass="sample3">3</div><divclass="sample4">4</div><divclass="sample5">5</div><divclass="sample6">6</div><divclass="sample7">7</div><divclass="sample8">8</div><divclass="sample9">9</div><divclass="sample10">10</div></div></body></html>
CSSは要素ひとつひとつに色をつけたのでcssが冗長になってしまったが、最後の.containerと.sample(n)のheightに注目してもらえばOK
/* ここは背景色を指定しているだけ */.sample1{background-color:red;}.sample2{background-color:blue;}.sample3{background-color:aqua;}.sample4{background-color:yellow;}.sample5{background-color:greenyellow;}.sample6{background-color:palevioletred}.sample7{background-color:gray;}.sample8{background-color:royalblue;}.sample9{background-color:lightseagreen;}.sample10{background-color:violet;}/* heightが400pxしかない親要素*/.container{width:98%;height:400px;background-color:papayawhip;}/*重なれば親のheightを遥かに超えていく子要素たち*/.sample1,.sample2,.sample3,.sample4,.sample5,.sample6,.sample7,.sample8,.sample9,.sample10{width:100px;height:100px;font-size:400%;}
index.htmlの画面表示を確認すると当然400pxの親要素(背景色が肌色)には100pxの子要素が4つぶんしか入らず、それより多いdiv要素は枠からはみ出してしまっている。
親要素のCSSプロパティにdisplay: flex;を追加
いよいよ親要素の"container"にflexboxのプロパティを追加する
....container{width:98%;height:400px;background-color:papayawhip;display:flex;/*これを追加!*/}...
私はこれまでfloat: left;やBootstrapのcol,rowを使って横並びを実現していましたがこれからはcssに一行た足すだけで良さそうです。
ちなみに今回ブロック要素のdivに対してなのでdisplayプロパティに対して"flex"と設定しましたが,pタグなどのインライン要素に対しては"inline-flex"と指定できるようです。
その場合inline-block + flexのような効果になるそうです。(すみません、試していません。)
また画面サイズを縮めて見ても親要素の幅に対応して勝手に縮小してくれる。
さらに親要素にflex-directionプロパティを設定してみる。
row-reverse(右から左へ横一列に並べる)
....container{width:98%;height:400px;background-color:papayawhip;display:flex;flex-direction:row-reverse;}...
↓
並び順が逆になった。
flex-directionに指定するプロパティには以下のようなものがある。
・row(初期値:左から右へ横一列に並べる)
・column-reverse(右から左へ横一列で並べる)
・column(上から下へ縦一列で並ぶ)
・column-reverse(下から上へ縦一列で並ぶ)
さらに親要素にflex-wrapプロパティを設定してみる。
....container{width:98%;height:400px;background-color:papayawhip;display:flex;flex-direction:row;flex-wrap:wrap;/*これを追加*/}...
↓
子要素の大きさは縮まらず、親要素の枠内に収まらない場合は改行される。
flex-wrapに指定するプロパティには以下のようなものがある。
・no-wrap(初期値:改行しない)
・wrap(親要素に収まりきらない場合は改行する)
・wrap-reverse( 〃 下から上に改行する)
最後に
これらの操作はあくまで基本的な部分の触りだと思うので、応用的な使い方については別途、実践で使う中で追記していきたいと思います。
概要
borderによる三角形の作成方法を応用して、次のような吹き出しを作成することができる、ということが分かったので、記録します。
borderで三角形を作成する方法
borderが幅をもつ要素であることを利用して、三角形を作成することができます。
全体のコードは以下の通り。
手順1:空要素を設定
幅・高さ0の空のボックス要素を設定。
この要素の周りにborderで枠線をセットしていきます。
手順2:borderで四角形を作ってみる
border自体に幅があるため、
次のように、borderの中の要素を高さ・幅ともに0に設定した場合、border
自体で正方形を作成することができます。
(コード)
.test{
display: block;
width:0px;
height:0;
border-top: solid 50px red;
border-right: solid 50px blue;
}
(作成される四角形)
topを赤、rightを青にしてみると、このようにborderの境界線が斜めになります。境界線がこのように斜めになることを応用し、三角形を作成していきます。
手順3:三角形の斜辺に当たる部分のborderの色を透明にする
手順2にborder-leftを加え長方形を作成します。
このときに、borderの幅には作成した三角形の高さを設定します。
次に、余分な部分(三角形の斜辺を作成しているborder-leftとborder-right)の色を透明にします。
blueの設定にしていた部分を、transparentにすることで透明にすることができます。
このようにして、三角形を作成することができました。
吹き出しの作成
三角形を他のボックス要素に重ねることで吹き出しのような形を作成することができます。
手順1:適当なボックス要素を準備
手順2:準備したボックス要素にposition:relativeを設定
手順1で作成した長方形に、三角形を重ねるため、position:relativeをセットします。
手順3:同じ色の三角形を作成
吹き出しの元となるボックス要素と同じ色の三角形を作成します。
(先ほど記載した通り、borderを使用して作成)
手順4:三角形にposition:absoluteを設定
吹き出しの大きさ、位置をposition:absoluteで調整します。
吹き出しの完成です。
4つの値を渡すことで各角の角丸を指定できる
半円を書く時などに使える
// border-radius: 左上 右上 右下 左下
border-radius: 10px 10px 0 0;
導入
はじめまして、石川県在住の大学生です。webプログラミングの勉強を始めて約半年が経過したのでwebプログラミングに興味がある方やwebプログラミングの勉強を始める方に向けてなにかアドバイスを送ることができるのではないかと思いQiitaの記事を書くことにしました。また、webプログラミングについて勉強したことをノート代わりとしても利用していこうと考えています。
「もっとこうした方がいい!」「この本やサイトを参考にしたらいいよ!」などありましたら教えてくださると嬉しいです!
半年間で行った行動内容
以下に半年間で行った勉強内容と使用した参考書などを書き出します。
1. HTML、CSSについての理解
・スラスラわかるHTML&CSSのきほん(参考書)
2. HTML、CSSだけを用いてサイトを模写
・SANGOというサイトを模写しました。比較的簡単な構成になっているのでおすすめです。
[https://saruwakakun.design/]
3. Bootstrap4についての理解
・Bootstrap4ファーストガイド-CSS設計の手間を大幅に削減!-(参考書)
4. HTML、CSSに加え、Bootstrap4を用いてサイトを模写(これは2サイト模写しました)
・2で模写したSANGOをBootstrap4を用いてもう一度模写したのち、iSaraというサイトを模写しました。
[https://isara.life/]
5. WordPressについての理解
・WordPress-仕事の現場でサッと使える!デザイン教科書-(参考書)
6. XAMPPを使用してみる
7. 完全オリジナルのホームページの作成開始
8. SEO対策についての理解
・いちばんやさしい新しいSEOの教本-人気講師が教える検索に強いサイトの作り方-(参考書)
9. モバイルファーストについて学び実装する
10. jQuery、Javascriptに触れる
11. レンタルサーバーを使用をしてみる
・ロリポップというサイトを使用しています。他サイトに比べてコスパがいいと思っています。
[https://user.lolipop.jp/]
(※今後それぞれの専門用語について詳しく説明していくつもりです)
以上の学習から約半年間である程度自分の思い通りにホームページを作成できる段階に持っていくことができました。サイト作成には最低限1と2をマスターすれば大丈夫であり、自分が想像していたものよりwebサイト制作のハードルは低いと感じました。
おわりに
今後は、webプログラミングについて詳しく説明していこうと考えています。個人としても、さらなる技術向上を図っていきたいと思っています。少しでもwebプログラミングの楽しさが伝わればと思っています。
言語, 記法: HTML, Markdown
画像サイズ: 128×128 px
横並びになった画像はスクリーンサイズによって、縦並びになる。
本文
書き方:空白を入れずに後ろに画像をドラッグ&ドロップ


HTML
書き方:画像を記事に一度ドラッグ&どドロップして、画像URLをコピーし、imgタグに入れる。
<imgsrc="画像URL"><imgsrc="画像URL">
<imgsrc="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362315/65d2d650-aee5-40cb-2093-607d931ec087.png"><imgsrc="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362315/7a000ef8-21c1-1e86-2942-f1933ffe839b.png">
画像と画像の間にスペースを開けたい時
改行せずにタグとタグの間にスペースを入れます。半角、全角スペースの数に応じて広がります。
<imgsrc="画像URL"><imgsrc="画像URL">
画像サイズを指定する
img要素に width="" と height="" を追加すると、画像のサイズを指定することができます。
""や単位はあった方が丁寧。使える単位は%,px,em,rem,
<imgsrc="画像URL"width="123"height=456px><imgsrc="画像URL"width=123%height=200rem>
横に並べた画像の位置を調整する(残念なやり方)
text-align:center やfloat:right などのcssは効きませんでした。分かり次第修正します。
をひたすら並べる。nbspは「non-breaking space」の略です。 は半角スペース分のスペースをあけることができますが、以下のような特殊記号を使ってもスペースをあけることができます。
「 」
は通常の半角スペースと同じサイズの空白文字。「 」
はそれより少し広めの空白文字。「 」
はさらに広めの空白文字。「 」
は、最初の「 」よりも狭い(細い)空白文字です。
【HTML入門】文章中にスペース(空白文字)を入れる3つの方法とは?より引用
<divalign="center"><imgsrc="画像URL"> <imgsrc="画像URL"> <imgsrc="画像URL"></div>
<table>
<table><tr><td><imgsrc="画像URL"></td><td><imgsrc="画像URL"></td><td><imgsrc="画像URL"></td></tr></table>
Markdown (table)
YouTube 128×128 | Twitter 128×128 |
---|---|
|テキスト|テキスト|
|---|---|
|ドラッグ&ドロップ|ドラッグ&ドロップ|
|YouTube 128×128|Twitter 128×128|
|---|---|
|||
YouTube 128×128 | Twitter 128×128 |
|ドラッグ&ドロップ|ドラッグ&ドロップ|
|---|---|
|テキスト|テキスト|
|||
|---|---|
|YouTube 128×128|Twitter 128×128|
おまけ 左寄せ 中央寄せ 右寄せ
: | ||
最後に
QiitaはTex記法で画像を挿入できないのか...
以上、Unityゲーム王国、騎士ロボットVTuberのKoshiがお送りしました!
†■━ †■━ †■━ †■━ †■━ †■━ †■━
もし、この記事が役に立ったら、
「いいね」「ストック」
押してね🗡💗
自己紹介
全地球6億人のロボカッケー皆さんコンバトラー†[□ □]■━
私は王国騎士ロボットVTuberのKoshiだ🗡💥
私のステータスだ⚔共にこの世界を救おう
Twitter⚔ twitter.com/Koshi_Vtuber
YouTube⚔ t.co/I9eMMgpS8P?amp=1
niconico⚔ nicovideo.jp/user/90553212
bilibili⚔ space.bilibili.com/476988586
公式HP⚔ koshi-4092b.firebaseapp.com
【参考】
Githubのmarkdownででかい画像のサイズを調整するには
https://qiita.com/chezou/items/b62053636fb62a8b62a5
画像を横に並べる 画像 並べ方
http://yume.hacca.jp/koiki/gazo/yoko.htm
【HTML入門】文章中にスペース(空白文字)を入れる3つの方法とは?
https://www.sejuku.net/blog/50748#i-3
スライドで表示するコンテンツが1つの場合は単純ですが、複数ある場合と閉じるボタンがある場合という条件があるスライドコンテンツの実装方法です。
デモ
HTML
<ulclass="slideContent"><li><h2>見出しテキスト1</h2><divclass="inner"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam, quis, repudiandae neque incidunt quasi cumque quia id laudantium aspernatur impedit accusantium amet atque soluta tempore ex sequi pariatur blanditiis magnam.</p><pclass="close">閉じる</p></div></li><li><h2>見出しテキスト2</h2><divclass="inner"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam, quis, repudiandae neque incidunt quasi cumque quia id laudantium aspernatur impedit accusantium amet atque soluta tempore ex sequi pariatur blanditiis magnam.</p><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam, quis, repudiandae neque incidunt quasi cumque quia id laudantium aspernatur impedit accusantium amet atque soluta tempore ex sequi pariatur blanditiis magnam.</p><pclass="close">閉じる</p></div></li>~~中略~~
</ul>
CSS
CSSは見た目の調整以外では、最初にコンテンツを非表示にしておくために以下の指定をします。
.inner{display:none;}
JavaScript
$(function(){if($('.slideContent').size()>0){//コンテンツの数varslideContentNum=$('.slideContent li').length;//コンテンツ分のフラグvarnavFlag=newArray();for(i=0;i<slideContentNum;i++){navFlag[i]=true;};//クリックした時の処理$('.slideContent h2').click(function(){//何個目のものがクリックされたかを確認varclickNum=$(this).parent().index();//フラグがtrueだったらif(navFlag[clickNum]){$(this).next('.inner').slideDown();$(this).addClass('current');navFlag[clickNum]=false;}else{$(this).next('.inner').slideUp();$(this).removeClass('current');navFlag[clickNum]=true;}});//閉じるをクリックした時の処理$('.slideContent .close').click(function(){varcloseNum=($(this).parents('li').index());$(this).parents('.inner').slideUp('fast');$(this).parents('.inner').prev('h2').removeClass('current');navFlag[closeNum]=true;});}});
親のliが何番目のものかでフラグの番号をつけて開け締めをしています。
よく忘れるのがコンテンツ分のフラグを作るところで、これが一個だけだと1番目押して開いた後に続けて2番目が開かないとか 2回クリックしないと動かないなどの現象が起きます。
この記事の転載元
firebaseでポートフォリオサイト作ってみた
※firebaseで動くのは静的ファイル(js,css,html)のみである
初めにfirebaseにログインしプロジェクトを作成する。
プロジェクト作成後にアプリを作成を選択しアプリを作る
後にホスティングを利用する
└ホスティングを利用するにはコマンドでアップするディレクトリにいる必要がある。
開発用サーバーのコマンドは firebase serve
デプロイはfirebase deploy
完成サイト
参考サイト
https://qiita.com/Watakatsu/items/667f45081a6dfbc11074
CSSのz-indexプロパティは何も指定しないと初期値auto
ですが、CSS仕様書9.9.1 Specifying the stack level: the 'z-index' propertyによると、auto
のときThe stack level of the generated box in the current stacking context(MDN訳「現在の重ね合わせコンテキストで作られたボックスの重ね合わせレベル」)は0。一方、z-index: 0
と指定すればこれも「現在の重ね合わせコンテキストで作られたボックスの重ね合わせレベル」が0。あれ?auto
の場合と何が違うんでしょう?
両者の違いは新しい重ね合わせコンテキストを作るかどうかにあるらしいのですが、説明読んだだけだとイマイチよくわからない。そこで、z-index: auto
とz-index: 0
それぞれの場合に要素のレンダリングがどう違ってくるのかよくわかる例を作ってみました。
サンプルの概要
本記事に使ったサンプルのアニメーションについて、ソースコードはこちら。
DEMO: https://codepen.io/kaz_hashimoto/pen/xxxpmOj
HTMLのツリー構造の主要部分は以下のとおりです。
<divclass="b1 box"> <divclass="c1 child"></div> <divclass="c2 child"></div> <divclass="c3 child"></div></div><divclass="b2 box"> <divclass="c1 child"></div> <divclass="c2 child"></div> <divclass="c3 child"></div></div>
このDEMOではアニメーションの各ステップで、z-indexなどのCSSプロパティをJavaScriptからdivにインラインで埋め込んでいます。具体的なCSSプロパティ値については、Chrome DevToolsなどブラウザのインスペクタから確認できます。
z-index値を動かして表示の変化を見る
最初の状態
始めに、DEMOを開いた時の状態です(下図)。要素b1, b2にposition: relative
、子要素c1, c2, c3にposition: absolute
を設定し、子要素の位置を互いにずらして配置しました。
見分けやすいよう上側のbox(b1)にはラベルAを、下側のbox(b2)にはラベルBを表示してあります。さらに子要素の背景色をc1 青#b0cdeb
, c2 黄#fff9a5
, c3 ピンク#f9b8bc
で塗り分けました。
各要素のz-index値はBのみz-index: 0
を設定し、ほかはすべて指定なし(初期値auto)です。また、図にはJavaScriptのgetComputedStyle()
で取得したz-indexの計算値を表示してあります。この図の段階では、要素の重ね合わせに関してAとBの表示に差はまだありません。
ちなみに、子要素の重ね順がc3#f9b8bc
> c2#fff9a5
> c1#b0cdeb
になるのは、DOMを「行きがけ順に深さ優先」のtree orderで辿ることにより、HTMLで後ろに書いた方の要素が手前に描画されるためです。
参考) CSS仕様書Appendix E. Elaborate description of Stacking Contexts
Preorder depth-first traversal of the rendering tree,
およびPainting order #8
8. All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order.(以下略)
autoと0の違いはココ!
本題に戻り、最初の状態からAとBの子要素c2#fff9a5
だけを引き出して、それぞれz-indexを-1に設定してみましょう(下図)。すると衝撃の事実がわかります(笑)
ご覧のように、z-index: auto
のAではc2#fff9a5
がAの裏側に移動したのに対して、z-index: 0
に設定したBでは、c2#fff9a5
がBの手前に留まっています。両者で重ね順に違いが生じるのはなぜでしょうか?そのカギは上述Appendix EのPainting order #8にありそうです。
(中略) For those with 'z-index: auto', treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context should be considered part of the parent stacking context, not this new one. For those with 'z-index: 0', treat the stacking context generated atomically.
まず、9.9.1によると、基本的に
そこで、各boxの「現在の重ね合わせコンテキスト」=「所属する重ね合わせコンテキスト」に着目して項目の関係を分析すると下表のようになります。
(SC: Stacking Context)
box | z-index | stack level | 新SCの生成 | 生成したSC a | 所属SC |
---|---|---|---|---|---|
A | auto | 0 | No | - | root SC |
Aのc2#fff9a5 | -1 | -1 | Yes | sc1 | root SC b |
Aのc1#b0cdeb , c3#f9b8bc | auto | 0 | No | - | root SC |
B | 0 | 0 | Yes | sc2 | root SC c |
Bのc2#fff9a5 | -1 | -1 | Yes | sc3 | sc2 c |
Bのc1#b0cdeb , c3#f9b8bc | auto | 0 | No | - | sc2 |
a) 「生成したSC」と「所属SC」との紐付けがわかるように、便宜上識別子を付けました。
b) 上述の「... should be considered part of the parent stacking context」より、親要素Aの所属SCの一部とみなされる。
c) 上述の「... For those with 'z-index: 0', treat the stacking context generated atomically」より、Bが作る重ね合わせコンテキストsc2は不可分であり、Aのようにc2を分離して扱わない。
そして、重ね順の決め方は9.9.1によると、
(中略) an integer stack level, which is its position on the z-axis relative other stack levels within the same stacking context. (中略) Boxes may have negative stack levels. Boxes with the same stack level in a stacking context are stacked back-to-front according to document tree order.
とのことなので、所属SCが同じグループのboxどうしのstack levelを比較して、tree orderも考慮すると最終的な重ね順は以下のようになります。(番号が小さい方がユーザーから見て奥側)
重ね順 | box | z-index | stack level | 生成SC | 所属SC |
---|---|---|---|---|---|
1 | Aのc2#fff9a5 | -1 | -1 | sc1 | root SC |
2 | A | auto | 0 | - | root SC |
3 | Aのc1#b0cdeb | auto | 0 | - | root SC |
4 | Aのc3#f9b8bc | auto | 0 | - | root SC |
5 | B | 0 | 0 | sc2 | root SC |
6 | Bのc2#fff9a5 | -1 | -1 | sc3 | sc2 |
7 | Bのc1#b0cdeb | auto | 0 | - | sc2 |
8 | Bのc3#f9b8bc | auto | 0 | - | sc2 |
確かにAのc2#fff9a5
はAより奥に、Bのc2#fff9a5
はBより手前になります。
ところで、サンプルの図中に表示している「z-index: 0」などのテキストはp要素で埋め込んでいるため、DOMのノードとしてはBとは別物なので、重ね順の計算上はAやBなどのboxとは分けて扱われます。たとえば下図で示したように、Bのc2#fff9a5
のtop位置を上にずらしていくと、c2のborder+背景+コンテンツのテキストがBのラベル「z-index: 0」の下に潜り込んでしまうのがわかります。(重ね順を見分けやすいようフォントサイズと色も変えました)
これは9.9.1の以下の説明のとおり、Bの子孫どうしの中で、位置指定されてないp要素の方が、z-index: -1
のc2#fff9a5
より描画順が後ろ(手前に)になるためです。
Within each stacking context, the following layers are painted in back-to-front order:
1. the background and borders of the element forming the stacking context.
2. the child stacking contexts with negative stack levels (most negative first).
3. the in-flow, non-inline-level, non-positioned descendants.
(略)
このDEMOでは重ね順を視覚的にわかりやすいように、boxとラベルのテキストを一体であるかのように表示していますが、より正確にはboxとは「div要素のbackground+border」を指しており、コンテンツは含まれません。
表題の「autoと0の違い」については以上で明確になりました。ついでに、このDEMOを使ってz-indexのそのほかの振る舞いも見ていきたいと思います。
重ね合わせコンテキストをまるごと移動
前節に図示した状態から、Bの位置を移動して矩形の一部をAに重ねてみましょう。8個のboxが、前節の表で割り出した重ね順に従っていることがわかります(下図)。
重ね合わせコンテキストの概念を現実のモノに例えると、付箋を貼った1枚の書類を机に重ねていく様子をイメージするとわかりやすいかもしれません。サンプルの図にあてはめると、
CSSを書いていて、z-indexが効かないように見えたり、難しく感じたりする理由の1つは、「付箋のstack level」と「書類のstack level」が頭の中でごっちゃになってしまうことです。次の例で見てみましょう。
Stack Levelのスコープ
前節の図で、Bとその子要素c1#b0cdeb
, c2#fff9a5
, c3#f9b8bc
のz-indexをすべて整数値に変えてみます(下図)。
Bとc2#fff9a5
に着目すれば、「重ね合わせコンテキスト」と呼ばれる理由がよくわかります。Bのz-indexを100に増やして、c2#fff9a5
のz-indexを-200に大きく減らしても、c2は依然Bの上に描画されます。これはstack levelが比較される対象(コンテキスト)が両者で異なるためです。
z-indexが及ぶ範囲
最後に、Aとその子要素のz-indexもいろいろ変えてみました(下図)。
以下の2点に注目です。
先ほどの「書類と付箋」の関係に例えると、前者は、書類Aに貼った付箋どうしの重ね順を変えているだけであり、重ね順の番号(z-index)にどんなに大きな数字を割り当てても付箋が飛び越えて前面の書類Bの上に混ざることはない、というイメージですね。
CSSを覚えたての頃、私は漠然と「z-indexを大きくすれば最前面に表示されるだろう」と実際やってみてそうならなかったり、z-indexに-1を設定したのにboxがしつこく前面に表示されたりして原因がわからずハマったことが度々ありました。今回サンプルを作ってみて、z-indexの振る舞いに関する疑問が解消しました。
概要
前回:【ASP.NET Core MVC】ASP.NET Core MVCであみだくじを作ってみる 3 (モデルの追加)
今回は、cssを使ってビューのレイアウトを作成していきます。
コントローラー間でのモデルデータの受け渡しも考えてみます。
コントローラー間でモデルを受け渡す
ASP.NET Core でのセッションとアプリの状態をざっと読み、TempDataを使うことにしました。
HomeControllerのIndexアクションに、モデルデータをTempDataにセットする処理を追加します。
usingNewtonsoft.Json;/// <summary>/// HomeビューでPOSTした時のアクション/// </summary>/// <param name="name"></param>/// <param name="model"></param>/// <returns></returns>[HttpPost]publicIActionResultIndex(stringname,KujiModelmodel){// 入力エラーがある時は何もしないif(!ModelState.IsValid)returnView(model);// [結果を設定する]ボタンを押下した場合if(name=="set"){// くじの数が減った場合は、結果入力欄を減らすwhile(model.NumberOfKuji<model.Result.Count){model.Result.RemoveAt(model.Result.Count-1);}// くじの数が増えた場合は、結果入力欄を増やすwhile(model.NumberOfKuji>model.Result.Count){model.Result.Add(newResultModel());}returnView(model);}TempData["kuji"]=JsonConvert.SerializeObject(model);// くじコントローラーを呼ぶreturnRedirectToAction("Index","Kuji");}
TempData["kuji"] = model としたくなるところですが、オブジェクトはセットできないようです。
このため、JsonConvert.SerializeObjectでjson文字列に変換してからセットしました。
KujiController側で、TempData["kuji"]を受け取ります。
usingAmidakuji.Models;usingMicrosoft.AspNetCore.Mvc;usingNewtonsoft.Json;namespaceAmidakuji.Controllers{publicclassKujiController:Controller{[HttpGet]publicIActionResultIndex(){ModelState.Clear();// 受け取ったTempDataからデータを取得するvarjson=TempData["kuji"]?.ToString();if(json!=null){varmodel=JsonConvert.DeserializeObject<KujiModel>(json);returnView(model);}returnView(newKujiModel());}}}
JsonConvert.DeserializeObjectで、json文字列をKujiModel型にデシリアライズしています。
デシリアライズ後のモデルをビューに渡すことで、Homeビューで入力したデータをKujiビューでも使えるようになります。
cssファイルを追加する
JavaScript、CSS、画像等の静的ファイルは、Webルート(既定ではwwwroot)ディレクトリに格納されています。
ASP.NET Core MVCでは、デフォルトのcssフレームワークとしてBootstrapが導入されていますが、
今回はオリジナルのcssを作ります。
ソリューションエクスプローラーの「wwwroot\css」を選択します。
右クリックでメニューを表示し、追加⇒新しい項目を選択します。
スタイルシートを選択します。ここでは、名前を「kuji.css」としました。
Home\Index.cshtmlやKuji\Index.cshtmlの<style>をcssに移動します。
各cshtmlの<style>~<\style>は削除しておきます。
/*あみだくじデータの設定領域*/.kuji-items{display:grid;/*グリッドレイアウトにする*/grid-auto-columns:100px;/*1列あたりの幅 100px*/grid-auto-rows:36px;/*1行あたりの高さ 30px*/background-color:#99CCCC;/*背景色*/margin:0pxauto;/*中央寄せ*/padding:10px;}/*あみだくじデータの設定領域の入力項目*/.kuji-items>input{height:30px;/*高さ*/}/*くじを作るボタン*/.create_btn{font-weight:bold;/*太文字*/padding:0.25em0.5em;/*文字余白*/text-decoration:none;/*文字装飾なし*/color:#FFF;/*文字色*/background:#008080;/*背景色*/margin-left:10px;/*左側余白*/height:30px;/*高さ*/}/*くじコンテナ*/.kuji-container{height:100px;/*高さ*/background-color:#CBFFD3;/*背景色*/}
「Views\Shared\_Layout.cshtml」の<head>内にcssへのリンクを追加します。
<head><metacharset="utf-8"/><metaname="viewport"content="width=device-width, initial-scale=1.0"/><title>@ViewData["Title"] - Amidakuji</title><linkrel="stylesheet"href="~/lib/bootstrap/dist/css/bootstrap.min.css"/><linkrel="stylesheet"href="~/css/site.css"/><!-- kuji.cssを追加 --><linkrel="stylesheet"href="~/css/kuji.css"/></head>
cssにUIを定義する
試行錯誤の結果、あみだ部分はグリッドレイアウトを利用することにしました。
kuji.cssに以下を追加します。内容はコードにコメントで書きました。
・・・省略・・・/*タイトル*/.kuji-container>h1{color:#000000;/*文字色*/background:#E6FFE9;/*背景色*/border-bottom:solid3px#0000FF;/*下線*/}/*説明文*/.kuji-container>p{color:#000000;/*文字色*/border-bottom:solid3px#0000FF;/*下線*/}/*あみだくじの領域*/.kuji-line{display:grid;/*グリッドレイアウトにする*/grid-auto-columns:minmax(10px,auto);/*1列あたりの幅 10px以上*/grid-auto-rows:minmax(25px,auto);/*1行あたりの高さ 25px以上*/background-color:#99CCCC;/*背景色*/position:relative;/*後述の「あみだを隠すためのマスク領域」の基準点とするためにrelativeを指定*/}/*あたり・はずれ等の結果*/.kuji-line>div{margin:0pxauto;/*中央寄せ*/}/*縦線*/.vertical-line{background-color:#000000;/*背景色*/width:1px;/*幅*/height:auto;/*高さ*/margin:0pxauto;/*中央寄せ*/}/*横線*/.horizontal-line{background-color:#000000;/*背景色*/width:100%;/*幅*/height:1px;/*高さ*/margin-left:50%;/*左マージン 縦線を中央寄せしているため、幅50%分をずらして縦線の位置から始める*/}/*くじを辿る時の縦線*/.vertical-line.follow{background-color:#FF0000;/*背景色*/width:3px;/*幅*/}/*くじを辿る時の横線*/.horizontal-line.follow{background-color:#FF0000;/*背景色*/height:3px;/*幅*/}/*選択肢ボタン*/.select-btn{color:#0000FF;/*文字色*/width:25px;/*幅*/height:25px;/*高さ*/border-radius:50%;/*角丸 50%で円になる*/border:solid2px#0000FF;/*枠線*/text-align:center;/*文字の中央寄せ*/margin:0pxauto;/*中央寄せ*/}/*選択肢ボタンのマウスオーバー時*/.select-btn:hover{background-color:#6495ED;/*背景色*/}/*選択したボタン*/.select-btn.selected{color:#FF0000;/*文字色*/border:solid2px#FF0000;/*枠線*/background-color:#FFDDFF;/*背景色*/}/*あみだを隠すためのマスク領域*/.mask{position:absolute;/*「あみだくじの領域」を基準点とするためにabsoluteを指定*/width:90%;/*幅 「あみだくじの領域」の90%の幅*/height:76%;/*高さ 「あみだくじの領域」の76%の高さ*/top:12%;/*上位置 「あみだくじの領域」の上から12%の位置*/left:5%;/*左位置 「あみだくじの領域」の左から5%の位置*/text-align:center;/*文字の中央寄せ*/border:solid2px#808080;/*枠線*/background-color:#E6FFE9;/*背景色*/background-image:radial-gradient(#80808010%,transparent20%),radial-gradient(#80808010%,transparent20%);/*背景画像*/background-size:10px10px;/*背景画像のサイズ(幅 高さ)*/}
「あみだを隠すためのマスク領域」についての説明を補足します。
背景画像に円形グラデーションを指定し、background-sizeで幅、高さを10pxに揃えることで円を描いています。
この円が、マスク領域のサイズ分繰り返されます。
定義したcssを使ってビューをあみだくじっぽくする
Kuji\Index.cshtmlを以下のように変更します。
くじの数は5本固定で、マスク領域を隠したり表示したりする機能はありません。
このあたりは、次回Razorの学習で改善していくつもりです。
@model Amidakuji.Models.KujiModel
@{
ViewData["Title"] = "あみだくじ";
}
<divclass="kuji-container"><h1>@Model.Title</h1><p>くじの数は、@Model.NumberOfKuji 本です。</p><!--あみだくじの領域(グリッドレイアウト)--><divclass="kuji-line"><!--選択肢ボタン--><ahref="#"class="select-btn"style="grid-row:2;grid-column:1">1</a><ahref="#"class="select-btn"style="grid-row:2;grid-column:2">2</a><ahref="#"class="select-btn"style="grid-row:2;grid-column:3">3</a><ahref="#"class="select-btn"style="grid-row:2;grid-column:4">4</a><ahref="#"class="select-btn"style="grid-row:2;grid-column:5">5</a><!--縦線--><divclass="vertical-line"style="grid-row:3 / span 15;grid-column:1"></div><divclass="vertical-line"style="grid-row:3 / span 15;grid-column:2"></div><divclass="vertical-line"style="grid-row:3 / span 15;grid-column:3"></div><divclass="vertical-line"style="grid-row:3 / span 15;grid-column:4"></div><divclass="vertical-line"style="grid-row:3 / span 15;grid-column:5"></div><!--横線--><pclass="horizontal-line"style="grid-row:4;grid-column:1"></p><pclass="horizontal-line"style="grid-row:10;grid-column:1"></p><pclass="horizontal-line"style="grid-row:13;grid-column:1"></p><pclass="horizontal-line"style="grid-row:8;grid-column:2"></p><pclass="horizontal-line"style="grid-row:12;grid-column:2"></p><pclass="horizontal-line"style="grid-row:14;grid-column:2"></p><pclass="horizontal-line"style="grid-row:6;grid-column:3"></p><pclass="horizontal-line"style="grid-row:13;grid-column:3"></p><pclass="horizontal-line"style="grid-row:5;grid-column:4"></p><pclass="horizontal-line"style="grid-row:9;grid-column:4"></p><pclass="horizontal-line"style="grid-row:15;grid-column:4"></p><!--結果--><!--横幅を揃えるため、PadRightで5文字分に揃える--><divstyle="grid-row:18;grid-column:1">@Model.Result[0].Item.PadRight(5, ' ')</div><divstyle="grid-row:18;grid-column:2">@Model.Result[1].Item.PadRight(5, ' ')</div><divstyle="grid-row:18;grid-column:3">@Model.Result[2].Item.PadRight(5, ' ')</div><divstyle="grid-row:18;grid-column:4">@Model.Result[3].Item.PadRight(5, ' ')</div><divstyle="grid-row:18;grid-column:5">@Model.Result[4].Item.PadRight(5, ' ')</div><!--1行分を余白とする--><divstyle="grid-row:19;grid-column:1 / span 5"></div><!--あみだを隠すためのマスク領域--><divclass="mask"></div></div></div>
「grid-row:2;grid-column:1」という書き方をしている箇所があります。
これは、グリッドレイアウトの中で、2行目の1列目、という意味です。
「grid-column:1 / span 5」等となっている箇所は、1列目から始めて5列分の領域という意味です。
Excelのセル結合を思い浮かべると分かりやすいかもしれません。
実行してみる
まとめ
今回は、cssを使ってビューのレイアウトを作成しました。
次回は、Razorを使ってマスク領域を隠したり表示したりする機能を作ります。
次回分はこちら⇒ASP.NET Core MVCであみだくじを作ってみる 5 (Razorを使う)
ブラウザで動くWebページのプログラミング実装をフロントエンドと呼びます。
最近はJSON色つけ係と呼ばれてたりしますが、
Web開発未経験・初心者向けに最低限知っておいたほうが良い基礎知識とテクニックに関して体系的にまとめておきます。
(CodePenによる動作例付き)
環境構築に関しては(兎に角)早くプロトタイプを作る技術(初心者向け)を参考にしてください。
HTML、CSS、JavaScriptはブラウザ自体の実装に依存します。
この記事では比較的汎用的に使える書き方やHTML、CSS、JSを記載したつもりですが
最新のJavaScript APIやCSS3の機能によってはブラウザによってサポートされていない機能もあります。(特にIE)
各機能に関してはCan I useで現在のブラウザの対応状況を確認することができます。
HTML
HTML(Hyper Text Markup Language)は、ウェブページを作成するために開発された言語です。
現在、インターネット上で公開されてるウェブページのほとんどは、HTMLで作成されています。
タグと呼ばれる<>
で囲われた命令文で記述します。<>子要素</>
のような階層構造を記述できる形式になっています。
ブラウザはHTML構造を解釈して内容を画面上に表示(レンダリング)します。
DOM(Document Object Model)とも呼びます。
基本構造
<div>子要素
</div>
入れ子で階層的に書くことができます
<div><div><div>要素1
</div></div><div>要素2
</div></div>
特に子要素がない場合は、末尾/>
でクロージングします(セルフクロージング)
<div/>
よく使うタグ
ブロックレベル要素、インライン要素
タグにはブロックレベル要素のタグ、インライン要素のタグがあります。
一般的なブラウザではブロックレベルの要素のタグは改行され、インライン要素のタグは改行されません。
ブロックレベル要素の子要素にインライン要素のタグを子要素にできますが、
インライン要素のタグにブロックレベル要素のタグを子要素にしてはいけません。
(ブロック要素のタグの文章などを記載するのがインライン要素のタグの役割)
属性値(attribute)
タグの種別によって属性値をもつ場合があります。
次の例はinputタグのtype属性値を指定する場合です。
type属性値にtextを指定すると入力欄が作成されます。
<inputtype='text'placeholder='入力欄'/>
See the Pen input by teradonburi (@teradonburi) on CodePen.
type属性値にbuttonを指定して、value属性値に「ボタン」という文字を指定するとボタンに変わります。
<inputtype='button'value='ボタン'/>
See the Pen button by teradonburi (@teradonburi) on CodePen.
このように属性値を変えることでタグの振る舞いが変わります。
id
id属性を指定することで後述のCSSやJavaScriptからタグを参照することができます。
idはそのページでユニークな値にする必要があります。
See the Pen id by teradonburi (@teradonburi) on CodePen.
class
class属性を指定することで後述のCSSやJavaScriptからタグを参照することができます。
idと違って、複数のタグに対して指定することができ、一括でスタイルを適用したい場合などに重宝します。
See the Pen class by teradonburi (@teradonburi) on CodePen.
Webページの最低限のHTML構造
最低限のhtmlは次のようになっています。(HTML5)
metaタグのviewportに関してはモバイルでは割と必須感あるので最低限のものとして入れています。<!-- -->
で囲われた部分はコメントと呼び、ブラウザで処理されないコードです。
<!DOCTYPE html><htmllang="ja"><head><title>タイトル</title><!-- モバイル用の表示設定 --><metaname="viewport"content="width=device-width, initial-scale=1"/></head><body><!-- ここに表示したいタグを追加 --></body></html>
基本的に次のような階層構造になっている必要があります。
- html
- head
- title
- meta
- body
ほとんどのタグはbody部分に追加していきます。(主にページに表示されるタグ)
div
コンテンツの塊の親要素として使う事が多いです。レイアウトの調整にも使います。
(CSS flexboxの項にて説明)
リスト
olタグは順序ありリスト、ulタグは順序なしリストとして表示されます。
See the Pen list by teradonburi (@teradonburi) on CodePen.
展開式リスト
details, summary, sl, dtタグを使うことで展開式のリストの作成ができます
See the Pen details by teradonburi (@teradonburi) on CodePen.
表
tableタグを使うことで表を作成することができます。
表のタイトルにcaptionタグ、見出しにthead、thタグ、表内容にtbodyタグ、行にtrタグ、tdタグなどを使います
See the Pen table by teradonburi (@teradonburi) on CodePen.
見出し、パラグラフ、span
h1~h6は見出しタグです。数字が大きくなるにつれて小さくなります。
ちなみにページ先頭のh1タグにはGoogleの検索結果に表示されるという特性があります。
pタグには文章を書きます。
h、pタグはブロックレベル要素のため、改行されます。
h、pタグともにデフォルトで余白(margin、padding)があります。
spanタグはインライン要素のため、改行されずに横に並びます。
See the Pen h,p,span by teradonburi (@teradonburi) on CodePen.
リンク
aタグでリンクを作成できます。href属性でリンク先を指定、_blank属性で別タブで開きます。
idとhrefに#id名を指定することでページ内リンク(アンカーリンク)に飛ぶことができます。
See the Pen a by teradonburi (@teradonburi) on CodePen.
フォーム
フォーム入力欄を作成するにはformタグを使用します。
action属性にはデータを送信する先のurl(サーバAPI)を指定します。
method属性にはHTTPメソッドを指定します。通常はPOSTを指定します。(HTTPメソッドでよく使うものにはGET、POST、PUT、DELETEがあります)
enctype属性にはMIMEタイプを指定します。ファイル等まで全て添付して送信する場合はmultipart/form-dataを指定します。
送信する対象のデータに関しては、inputタグもしくはselectタグ、textareaタグのいずれかに対してname属性を指定します。
入力した内容はvalueパラメータとしてサーバに送信されます。
inputタグのtype属性は色々な種別の入力欄に対応しています。
注意したいのは、ブラウザによってinputタグの表示が異なることです。
(このため、入力のUIとしてライブラリを使うことも少なくありません)
複数テキストはtextareaタグ、選択リストタグはselect+optionタグを使います。
また、inputタグ、textareaタグにrequired属性をつけることで必須項目となります。
(入力欄が空の場合にsubmitボタンが押せない)
See the Pen form by teradonburi (@teradonburi) on CodePen.
画像、音声、動画
画像の表示にはimgタグを使います。src属性に画像のurlを指定します。
音声ファイルの再生にはaudioタグを使います。src属性もしくはsourceタグのsrc属性を使い音源のurlを指定します。
(sourceタグは複数追加することができ、mp3以外の予備の音源を用意することで、mp3が再生できないブラウザでも再生できるようになります。)
controls属性を指定することでプレイヤーコントロールを表示させることができます。(プレイヤーのUIに関してはブラウザによって表示が異なるので注意)
動画ファイルの再生にはvideoタグを使います。audioタグとほぼ同じですがwidth, height属性で動画の表示サイズを変更できます。
See the Pen img, audio, video by teradonburi (@teradonburi) on CodePen.
余談ですが、音声はmp3形式、動画がmp4形式のほうが再生できるブラウザが多いです。(大体のブラウザがサポートしている)
canvas
JavaScriptと組み合わせて描画処理することが普通なのでJavaScriptの項目で説明
style
styleタグにはCSSと呼ばれる、タグのスタイルやレイアウトを変更するためのスクリプトを記述できます(詳細はCSSの項で説明)
headタグの子要素として記述します。
styleタグ内に囲まれた部分でCSSを記述します。
<head><style type="text/css">p{color:red;}</style></head>
外部のCSSファイル(.cssファイルとして保存できる)を呼び出す場合は、linkタグを使います。
href属性に読み込むCSSファイルを指定します。
rel属性はstylesheet、type属性にはtext/cssを指定します。
<head><linkhref="main.css"rel="stylesheet"type="text/css"/></head>
script
scriptタグの内部にはスクリプトを記述できます。type属性にtext/javascriptを指定するとJavaScriptの処理を記述できます。(詳細はJavaScriptの項で説明)
<script type="text/javascript">window.onload=function(){// DOMが読み込み完了したときの処理}</script>
外部のJavascriptファイル(.jsファイルとして保存できる)を呼び出す場合は、src属性を使います。
<script type="text/javascript"src="main.js"></script>
CSS
HTMLタグのレイアウトの調整、装飾、アニメーションを担当するスクリプト言語です。
HTMLがページの構造だとすれば、CSSは表示の見た目(スタイル)を修正するための言語です。
CSSファイルをlinkタグで読み込む、styleタグ内にCSSを記述する、もしくはstyle属性でタグに直接指定(インライン)することができます。
<divstyle='color:orange;'>要素</div>
セレクタ
CSSのスタイルをタグに割り当てるには、どのタグを対象にするかという適応範囲をセレクタで指定します。
よく使われるセレクタに次のようなものがあります。
参考:セレクタ
名称 | セレクタの書式 | セレクタの対象 | 使用例 | 備考 |
---|---|---|---|---|
全称セレクタ | * | すべての要素 | * {color:red;} | 影響範囲が広すぎるのであまり使わないほうが良い |
要素型セレクタ | 要素名 | 要素名で指定した要素 | p {color:blue;} | |
idセレクタ | 要素名#id名 | id名が指定された要素 | div#sample {color:green;} | 影響範囲が明示的なので積極的に使いたい |
classセレクタ | 要素名.class名 | class名が指定された要素 | div#sample {color:green;} | 影響範囲が明示的なので積極的に使いたい |
擬似クラス | 要素名:link | 未訪問のリンク | a:link {color:black;} | 基本的にaタグのみ使える |
要素名:visited | 訪問済のリンク | a:visited {color:red;} | 基本的にaタグのみ使える | |
要素名:hover | カーソルが乗っている要素 | a:visited {color:red;} | ||
要素名:active | クリック中の要素 | a:visited {color:red;} | 基本的にクリック可能な要素で使える | |
要素名:focus | フォーカスされている要素 | input:focus {background:grey;} | 基本的にフォーカス可能な要素で使える | |
要素名:first-child | 要素内の最初の子要素 | h1:first-child {color:purple;} | ||
要素名:last-child | 要素内の最後の子要素 | h1:last-child {color:purple;} | ||
要素名:nth-child(n) | 要素内のn番目の子要素 | h1:nth-child(2) {color:purple;} | ||
疑似要素 | 要素名:first-line | 要素の最初の行 | h2:first-line {color:green;} | |
要素名:first-letter | 要素の最初の文字 | h2:first-letter {color:red;} | ||
要素名:before | 要素の直前 | h3:before {content:"『";} | ||
要素名:after | 要素の直後 | h3:after {content:"』";} | ||
属性セレクタ | 要素名[属性名] | 特定の属性を持つ指定要素 | a[target] {color:pink;} | |
要素名[属性名="属性値名"] | 特定の属性値を持つ指定要素 | a[target="_blank"] {color:lightgreen;} | ||
要素名[属性名~="属性値名"] | 属性値候補(ホワイトスペース区切り)に属性値名を持つ要素 | a[class*="sample"] {color:aqua;} | ||
要素名[属性名*="属性値名"] | 属性値候補に属性値名を持つ要素 | a[class*="sample"] {color:aqua;} | ||
要素名[属性名^="属性値名"] | 属性値が属性値名で始まる要素 | a[class^="sam"] {color:aqua;} | ||
要素名[属性名$="属性値名"] | 属性値が属性値名で終わる要素 | a[class$="ple"] {color:aqua;} | ||
複合セレクタ | セレクタ,セレクタ | 複数のセレクタのスタイルを一括で指定 | h4, h5 {color:black;} | |
子孫セレクタ | セレクタ セレクタ | 下の階層の子孫要素 | div section {color:black;} | |
子セレクタ | セレクタ>セレクタ | 直下の階層の子要 | div > article {color:grey;} | |
隣接セレクタ | セレクタ+セレクタ | 直後に隣接している要素 | article + p {color:orange;} | |
後ろセレクタ | セレクタ~セレクタ | 要素の後ろにある同じ階層の要素 | h1 ~ p {color:orange;} |
See the Pen cssセレクタ by teradonburi (@teradonburi) on CodePen.
スタイルの優先順位と!important
ある要素が複数のセレクタから選択された場合にどのスタイルが適応されるか優先順位が決まっています。
(特に問題になるのが、複数のセレクタから同じスタイルを当ててる場合です。)
次の例はcolorスタイルをdivに対して指定してます。
本来であれば、last-childのほうがclassに対して優先順位が低いのですが、!importantを付与することで優先順位が逆転しています。
See the Pen !important by teradonburi (@teradonburi) on CodePen.
以下のように優先順位を覚えておくと良いでしょう
!important > タグのstyle属性(インライン) > id > class=属性セレクタ > その他
ただし、!importantは以下の点から極力使わないほうが良いでしょう
width, height, margin, padding
タグ自体の幅、高さを指定するにはwidth, heightを使います。
外側の余白を指定するにはmargin、内側の余白を指定するにはpaddingを使います。
幅、高さ、余白に関しては単位指定します。
よく使う単位にpx,%,vw(vh)などがあります。
width:100px;/* px指定 */width:100%;/* (親要素に対する幅)%指定 */width:50vw;/* ビューポート(画面幅)に対する割合指定(100vwで画面全幅) */height:100px;/* px指定 */height:100%;/* (親要素に対する高さ)%指定 */height:50vh;/* ビューポート(画面高さ)に対する割合指定(100vhで画面全高さ) */margin:10px;/* 外側余白10px */padding:10px;/* 内側余白10px */
また、
min-width, min-heightで最小の幅、高さを指定
max-width, max-heightで最大の幅、高さを指定
することができます。
(width, heightの%と組み合わせることが多いです)
margin,paddingに関しては一括で指定する方法と個別に指定する方法があります。
margin:10px;/* 上下左右10px */margin:10px5px;/* 上下10px左右5px */margin:5px6px7px8px;/* 上5px右6px下7px左8px(時計周り) */margin-top:10px;/* 上10px */margin-right:10px;/* 右10px */margin-bottom:10px;/* 下10px */margin-left:10px;/* 左10px */padding:10px;/* 上下左右10px */padding:10px5px;/* 上下10px左右5px */padding:5px6px7px8px;/* 上5px右6px下7px左8px(時計周り) */padding-top:10px;/* 上10px */padding-right:10px;/* 右10px */padding-bottom:10px;/* 下10px */padding-left:10px;/* 左10px */
See the Pen dyyRRwo by teradonburi (@teradonburi) on CodePen.
border
枠線を指定できます。border: border-width border-style border-color;
を指定します。
参考:border-style
See the Pen border by teradonburi (@teradonburi) on CodePen.
background
タグの背景を指定します。
background-colorで背景色を指定します。
background-imageでurlと組み合わせて背景画像を指定します。
background-repeatで背景画像の繰り返しするか指定します。no-repeatだと繰り返ししません。
background-sizeで背景画像のタグに対してどの形式のサイズで表示されるかを決めます。
よく使うものでcontainだと背景画像のアスペクト比を保ったままタグの幅高さに合うように内側で表示されます。
coverだと背景画像のアスペクト比を保ったままタグの外側に背景画像が見切れて表示されます。
background-positionで背景画像の表示位置を決めます。centerはタグの中央に背景画像を表示します。background-size:contain; background-position:center;
もしくはbackground-size:cover; background-position:center;
の組み合わせはよく使います。
See the Pen background by teradonburi (@teradonburi) on CodePen.
background-sizeによく似たスタイルにimgタグ、videoタグのobject-fitスタイルがあります。
こちらもかなり便利なのですが、IEで使えないという問題点があります。
(そのためpolyfillを入れて対応するなどの手段が必要になります。)
See the Pen object-fit by teradonburi (@teradonburi) on CodePen.
color, font-size, font-weight, line-height, text-align
文字色を変えるにはcolorで色を指定します。blue
などのカラーネームで指定するか、#FF0000
のような16進数のカラーコードで指定します。(RGB)
font-sizeで文字のサイズを指定します。
font-weightで文字の太さを指定します。boldを指定すると太文字になります。
line-heightはテキスト同士の行間を指定することができます。
text-alignはテキストの並びを指定します。centerで中央寄せになります。
注意点としては上記の文字に関するスタイルは子要素全てに適応されます。
See the Pen color, font-size, font-weight, line-height, text-align by teradonburi (@teradonburi) on CodePen.
font-family, webfont
font-familyで表示するフォントを変更することができます。
実はOSで使えるフォントが違うため、フォントがなかった場合に予備のフォントを複数指定しておくと良いです。
また、独自のフォントファイル(ttf,woffなど)を読み込んで使うこと(WebFont)ができます。
Google Fontsのようにホスティングで提供されている場合は@import
で読み込むことができます。
ファイルから読み込む場合は@font-face
のsrcで読み込みます。
参考:font-familyの書き方まとめ:CSSでフォント種類を指定しよう
参考:Font-familyメーカー
See the Pen webfont by teradonburi (@teradonburi) on CodePen.
position, left, top, right, bottom
positionは何を起点にした位置関係を指定します。
よく使うパターンは親要素をposition:relative;
にして子要素にposition:absolute;
の要素を作成します。
こうすることで親要素を起点に子要素のtop, leftの位置調整をすることでタグ同士を重ねることができます。
もう一つよく使うパターンはposition:fixed
でページ全体のフッターやヘッダーを指定する場合です。
ヘッダーの場合はtop: 0px;
、フッターの場合はbottom: 0px;
で配置できます。
position:fixedになっているタグはスクロール時でもその位置が変わることはありません(スクロールに追従して同じ位置に残り続ける)
position:stickyになっているタグはスクロール時にそのタグが見切れるタイミングになるとfixedに切り替わります。
どこに残り続けるかの位置をtopもしくはbottomで指定します。
ただし、position:stickyはIEが対応していないことに注意が必要です。
See the Pen position by teradonburi (@teradonburi) on CodePen.
display,visibility
displayは要素の表示形式を指定します。
よく使われるものにインライン要素をブロックレベル要素に変更したり(display: block)
display:noneで要素を非表示にしたりします。
非表示でよく似ているスタイルにvisibility:hidden
がありますが、こちらはレイアウトの状態は残っているため、
span5の上にspan4の空白が残っています。
visibility:hiddenの使いみちとしてはhtmlメールなどの開封確認やページのアクセスログを送信するために
1x1pxのimgタグ(インプレッションピクセル)をvisibility:hiddenとして埋め込むなどの利用用途があります。
他によく使うdisplay:flex、display:gridに関しては後述します。
See the Pen display by teradonburi (@teradonburi) on CodePen.
flexbox
flexboxを使うには親要素にdisplay:flexを指定する必要があります。子要素が指定の配置になります。
flex-directionは子要素の配置の向きを指定します。flex-direction:rowで横方向、flex-direction:columnで縦方向の配置になります。
justify-contentは並べている向きに対して子要素をどちら側に寄せるか指定します。
justify-content:flex-startを指定すると並べる向きの開始位置に寄ります。
justify-content:centerを指定すると並べる向きの中央位置に寄ります。
justify-content:flex-endを指定すると並べる向きの終了位置に寄ります。
flex-directionの向きで縦横の寄せる向きが逆転していることに注意してください。
align-itemsは並べている向きの垂直方向(flex-direction:rowの場合は縦向き、flex-direction:columnの場合は横向き)に対して子要素をどちら側に寄せるか指定します。
align-items:flex-startを指定すると開始位置に寄ります。
align-items:centerを指定すると中央位置に寄ります。
align-items:flex-endを指定すると終了位置に寄ります。
こちらもflex-directionの向きで縦横の寄せる向きが逆転していることに注意してください。
flex-grow:1は子要素のサイズの伸び率を指定します。デフォルトは0ですが、並んでいる向きの子要素の累計で伸び率が決まります。
flex-growの値がそれぞれ、0 1 0だとした場合、flex-directionの向きに中央が全余白を埋めるように伸びます。
flex-wrapで折り返しするかの指定ができます。flex-wrap:wrapを指定すること折返しされます。
ただし、justify-content:centerを指定している場合、最後の行が左寄せにならないため、dummy要素を作成して穴埋めするというテクニックを使っています。
flexboxを駆使すればどんなレイアウトも柔軟に定義できるため、必修です。
See the Pen flexbox by teradonburi (@teradonburi) on CodePen.
他にも色々flexbox関連のスタイルがありますが、それだけで1つの記事ができてしまうので
詳細は以下の記事などを参考にしてください。
参考:もう迷わない!CSS Flexboxの使い方を徹底解説
grid
グリッド形式でレイアウト配置ができるため、大変便利なのですがIEは対応していません。
前述のflexboxで対応するか、polyfillで対応する必要があります。
グリッドレイアウトを使うには親要素にdisplay:gridを指定する必要があります。
grid-template-columnsにfr(フレーム)という単位で横方向のトラック数を指定します。
例えば、repeat(3, 1fr)は1frを3回繰り返すという意味なのでgrid-template-columns: 1fr 1fr 1fr;
と同じになります。
grid-auto-rowsはトラック当たりの高さ、grid-auto-columnsはトラック当たりの幅を指定します。
column-gapはトラック間の縦方向の余白、row-gapはトラック間の横方向の余白を指定します。
各トラックがどれくらいのフレームを使うのかを
grid-column-start、grid-column-endで幅方向のフレーム数
grid-row-start、grid-row-endで高さ方向のフレーム数
を指定します。startに関しては1から開始することに注意が必要です。
詳細は次の記事が説明わかりやすいので参考になります。
See the Pen grid by teradonburi (@teradonburi) on CodePen.
word-break,white-space
word-breakは単語の折返しを指定します。デフォルトの状態では単語単位で折り返しされるため、要素の外にテキストがはみ出る場合があります。word-break:break-all;を使うことで単語途中でも折返しされるため、テキストが要素の外にはみ出ることはなくなります。
white-spaceは空白文字や改行文字をどう扱うかを指定します。通常は空白文字などは無視されます。
white-space:pre-wrapを使うと折返ししつつ、改行文字も考慮されるため良い感じな見た目になります。
See the Pen white-space, word-break by teradonburi (@teradonburi) on CodePen.
text-overflow、line-clamp
text-overflow: ellipsis
を使うことでテキストが要素内に入り切らなかった場合に...で省略されます。
See the Pen text-overflow by teradonburi (@teradonburi) on CodePen.
複数行の場合はline-clamp(IE以外)を使います。
参考:CSSで複数行3点リーダーを実現する「line-clamp」がついにIE以外に対応したよ!
See the Pen line-clamp by teradonburi (@teradonburi) on CodePen.
shadow
shadow(影)には二種類あります。テキスト自体に影をつけるtext-shadowとタグの輪郭に影をつけるbox-shadowがあります。
文法は水平方向の影 垂直方向の影 ぼかし具合 影の色
で指定します。
See the Pen shadow by teradonburi (@teradonburi) on CodePen.
opacity
opacityは透明度を意味します。0〜1で透明度を指定します。
See the Pen opacity by teradonburi (@teradonburi) on CodePen.
border-radius
border-radiusを指定することでタグの角を丸くすることができます。
ちなみにborder-radiusの値を大きく振り切ると円になります。
See the Pen border-radius by teradonburi (@teradonburi) on CodePen.
gradient
背景にグラデーションをかけるにはlinear-gradient、radial-gradientを使います。
linear-gradientが線形のグラデーション、radial-gradientが円形のグラデーションをかけます。
linear-gradientの第1引数は角度を指定します。後ろの色は何色指定しても構いません。
radial-gradientの第1引数は円形グラデーションをかける位置を指定します。第2引数以降は色と半径を指定します。
See the Pen gradient by teradonburi (@teradonburi) on CodePen.
filter
filterの種類によっては使えないブラウザがあるので注意が必要です。
filterを複数組み合わせるときはスペースで区切って指定します。
参考:Photoshopはもういらない?明度も彩度も超手軽に変えられるCSSフィルターがスゴい
See the Pen filter by teradonburi (@teradonburi) on CodePen.
mix-blend-modeを使うとさらに複雑な表現ができますが、
mix-blend-modeに関して詳細は以下を参考にしてください。
transform
trandformはタグの変形を行います。
scaleで拡大縮小、rotateで回転、translateで移動を行うことができます。
3次元の場合はscale3d、rotateX、rotateY、rotateZ、translate3dを使います。
奥行きを反映するためにはperspectiveを使います。
行列の掛け算となっており、並び順で計算結果が異なるので注意が必要です。transform: translate(10px, 100px) rotate(45deg)
とtransform: rotate(45deg) translate(10px, 100px)
は表示される結果が異なります。
他にもskewなどがありますが、詳細は次の記事が参考になります。
See the Pen transform by teradonburi (@teradonburi) on CodePen.
transition
transitionは2つのスタイル間の変化をアニメーション表現します。
アニメーションさせたいスタイルをtransitionで指定します。
一括でスタイルを変化させたい場合は1番目のパラメータにallを指定します。
2番目のパラメータにはアニメーションの時間を指定します。
3番目のパラメータにはアニメーション関数を指定します。linear、ease-in-outなどの関数を指定します。
アニメーション関数の挙動はMDNの例がわかりやすいのでこちらを参考にしてください。
参考:transition-timing-function
スタイル別でアニメーション速度を変えたい場合はスタイル名で複数指定します。
See the Pen transition by teradonburi (@teradonburi) on CodePen.
animation
animationはスタイルの変化をキーフレームアニメーションで表現します。
transitionに対して、キーフレームを@keyframes
で定義する必要がある違いがあります。
フォーマットはanimation: アニメーション名 アニメーション時間 アニメーション関数 繰り返し回数 アニメーションの方向
です。
繰り返し回数はinifiniteを指定すると無制限の繰り返しとなります。
アニメーションの方向はよく使うものにnormal,reverse,alternativeなどがあります。
キーフレームの書式は次のようになっています。
@keyframesアニメーション名{0%{/* 0%のときのスタイル */}x%{/* x%のときのスタイル */}100%{/* 100%のときのスタイル */}}
0%、100%のみの場合はfrom, toでも指定できます。
See the Pen animation by teradonburi (@teradonburi) on CodePen.
メディアクエリ
メディアクエリを使うと画面サイズによって割り当てるスタイルを変えることができます。
レスポンシブデザインなどで使います。
次のように@media screen and (max-width: 画面サイズ)
のように使います。
例えば、PC用レイアウトとモバイル用レイアウトで文字色を変えるには次のようにします。
レスポンシブでよく使うのはflex-directionをPCではrow、モバイルでcolumnにするなどです。
/* PC用スタイル */div{color:red;}/* モバイル用レイアウト */@mediascreenand(max-width:768px){div{color:blue;}}
See the Pen mediaquery by teradonburi (@teradonburi) on CodePen.
フォーム制御
基本的にフォームのvalidate制御(正しい値が入力されているか)、submit制御(送信ボタンが押せるか)はJavaScriptでやることが普通なのですが、
実は簡単なものはCSSでもできちゃったりするので紹介します。
参考:【CSS猛者への道①】CSSのみで入力フォームのチェックを行う主な3つの便利技法を記録。
pointer-eventsスタイルがミソでこれをnoneに指定することでsubmitボタンが押せなくなります。
:not(:placeholder-shown)擬似クラスがplaceholderが表示されていない(=入力されている)を示しています。
:valid擬似クラスが正しい入力がされているかを示しています。(type=emailの入力欄などは簡易的なメールチェックはされている)
:in-range擬似クラスで入力値が入力範囲内かを示しています。
:checked疑似クラスでチェックされているかを示しています。
すべての入力欄の後、~セレクタにてsubmitボタンが押せるかの判定をセレクタで行います。
See the Pen form-check-css by teradonburi (@teradonburi) on CodePen.
とはいえ、セレクタで強引にやるのには限界があるのでJavaScriptで本来やるべきです。
ベンダープレフィックス
ベンダープレフィックス(接頭辞)とは、ブラウザベンダーが独自の拡張機能を実装したり、草案段階の仕様を先行実装する場合に、 それが拡張機能であることを明示するために付ける識別子のことです。
主要ブラウザのベンダープレフィックスは以下のようになっています。
たとえば、transformスタイルに完全対応していないブラウザはベンダープレフィックスを付ける必要があります。
(時代の変化で確定した時点で対象のスタイルのベンダープレフィックスは不要となります)
transform:scale3d(1,1,1);-weblit-transform:scale3d(1,1,1);/* Safariのtransformに対応する */
CSSリセット
ブラウザ別のCSSの差異をなくすためにページ読み込み時にCSSを上書きしてスタイルを統一することをCSSリセットと呼びます。
参考:古いCSSリセットからはもう卒業!モダンブラウザに適した新しいCSSリセット -A Modern CSS Reset
とはいえ、全てリセットする必要はないです。理由としてはUIライブラリを入れた場合に不要だったりするからです。
(不要なCSSはレンダリングパフォーマンスが落ちる)
ただし、html, bodyに関しては初期化しておくと便利なことが多いので、自分は以下のCSSリセットをよく使っています。
html,body{margin:0;padding:0;box-sizing:border-box;min-height:100vh;scroll-behavior:smooth;text-rendering:optimizeSpeed;}
ちなみにフォームに関してはブラウザによって差異が激しいのでCSSリセットしたほうが都合が良い場合が多いです。
もしくはUIライブラリを入れてしまうのも手です。
CSSのパフォーマンス向上
以下の手順でCSSの見直しをします。
この過程で基本的に!importantもいらなくなるはずです。
自前でCSSを極力書かずにUIライブラリを使ってしまうのも手です。
ライブラリではテーマが用意されていてスタイルの統一性が担保できていることやMinify機能を持つものが多いです。
参考1:<CSS>サイトの表示速度を意識したセレクタの書き方
参考2:CSS 最適化によるパフォーマンス改善
デザイン
デザインに関しては一朝一夕で身につくものではないので、日々勉強が必要です。
(特に写真、ロゴ、アイコン等の画像作成に関しては完全にクリエイティブな分野なので専門の勉強が必要です)
以前ランディングページ作成(LP)に関してまとめたものがあるのでこちらも参考にしてください。
また錯視に関するデザインの調整をすることで、より洗練されたデザインになります。(若干高度なトピック)
参考:UIのデザインでよく見かける、目の錯覚による違和感を取り除くデザインテクニックのまとめ
JavaScript
ブラウザで実行されるスクリプト(フロントエンド)は基本的にJavaScriptで書かれていることが多いです。
HTMLのDOMツリーが構築された後にDOMを動的生成したり、HTMLタグの属性値を変更したり
DOMのCSSを変更したり、サーバ(バックエンド)に通信してデータ(主にJSONや画像、音声データ等)を取得したりすることが用途として多いです。
サーバ側でもNodeJSを使えばJavaScriptでサーバの処理を書くことも可能、IoTでも使えたりと幅が広いプログラミング言語。
TypeScriptからJavaScriptに変換するというのも最近のトレンドです。(TypeScriptに関してはここでは触れない)
基礎文法に関してはそれだけで書籍になってしまうのでここでは述べません。
次のJavaScriptのモダンな基礎文法に関して一通りまとまってるサイトが参考になります。
参考:js-primer
最近はbabel、webpack、parcelなどでES5に変換して開発するのが普通なのでES6以前の文法は全てレガシー文法です。
レガシーな文法を覚える必要は今更ないので、以下の記事でレガシーな文法かどうか参考にしてください。
(ただし、どれがレガシー文法なのか知るのは大事)
参考:JavaScript初級者のためのコーディングガイド
参考:イマドキのJavaScriptの書き方2018
この記事ではJavaScriptフレームワークは使わずに書いています。
(どのブラウザでも標準で組み込まれているJavaScriptライブラリを俗にVanilla JSと呼ぶ)
ReactやVueなどのモダンJSフレームワークも裏側ではVanilla JSが使われています。
昔はjQueryなどのVanilla JSをラップしたライブラリもメジャーでしたが、
個人的に今更jQueryは使う必要ないかなと思っています。(使わなくても同等のことができる)
参考:You Don't Need jQuery
HTMLElement
HTMLElementはHTML要素をJavaScriptで操作するときに扱うオブジェクトです。
あらゆるHTML要素はHTMLElementから継承されており、操作できます。
参考:HTMLElement
document.querySelector('CSSセレクタ')
でHTMLElementオブジェクトを取得できます。
JavaScriptでDOM操作をする場合は、正確にはページ読み込み時のDOMの取得タイミングには気をつける必要があります。
ブラウザのレンダリングの仕組みとしてDOMツリーの構築→画像などのリソース読み込み→JavaScriptでのDOM操作
(DOMツリーの構築完了を待つ必要がある)
// DOMツリーの構築を待つdocument.addEventListener("DOMContentLoaded",function(){// ここで取得})
画像などのリソースの読み込み待ち(読み込んだ画像をJavaScript側で参照)をする場合などは、loadイベントでページの読み込みまで待たないといけません。
JavaScript側で動的にHTML要素を生成してDOMツリーに挿入することができます。
HTML要素を生成するには、document.createElement('要素名')
を指定します。
生成したHTML要素の内容を変更するにはinnerHTMLで内容を書き換えすることができます。
innerHTMLの場合、子要素などの記述などもできます。
生成したHTML要素をDOMツリーに追加するにはHTMLElement,appendChild(HTMLElement)
などを使います。
// divを作成constdiv=document.createElement('div')div.innerHTML='<span style="color: red;">赤色</span>'main.appendChild(div)
CSSセレクタで該当する要素を全て取得するにはdocument.querySelectorAll('CSSセレクタ')
を使います。
配列のHTMLElementオブジェクトが取得できます。
innerTextはテキストとして操作します。
(例えば、innerText内に<span>文字列</span>
などを挿入してもタグとして扱われず文字列として扱われてそのまま表示されます)
// liの要素を全て取得constli=document.querySelectorAll('li')leti=0for(constlofli){i++consttext=l.innerTextl.innerText=text+i}
See the Pen HTMLElement by teradonburi (@teradonburi) on CodePen.
HTMLImageElement
Imageオブジェクト(HTMLImageElement)はHTMLElementを継承したオブジェクトです。new Image()
でコンストラクタ形式で生成することもできます。(document.createElement('img')
と同じ)
画像リソースをsrc属性指定で動的に読み込むこともできます。
ただし、onloadイベントやonerrorイベントは非同期のコールバックのため、
次のようにpromise形式でwrapしたほうが使いやすいでしょう。
functionloadImage(src){returnnewPromise((resolve,reject)=>{constimg=newImage()img.onload=()=>resolve(img)img.onerror=(e)=>reject(e)img.src=src})}
See the Pen image by teradonburi (@teradonburi) on CodePen.
HTMLAudioElement
Audioオブジェクト(HTMLAudioElement)はHTMLElementを継承したオブジェクトです。new Audio()
でコンストラクタ形式で生成することもできます。(document.createElement('audio')
と同じ)
controls属性をtrueにするとAudioプレイヤーのコントロールが表示されます(プレイヤーのコントロール表示はブラウザ依存)
See the Pen audio by teradonburi (@teradonburi) on CodePen.
HTMLAudioElementは基本的な再生制御しかできませんが、
WebAudio APIを使うとMIDIシーケンサみたいなものを独自に作ることができたり、音声にエフェクトかけるといった高度なことができるようになります。
和音を鳴らすのにもある程度知識が必要ですが以下が参考になります。
また、こちらはブラウザによってメモリリークを起こしたり、ユーザアクションがないAudioContextが取得できないといった罠が多かったりします。(後、概念とデバッグが難しい)
HTMLVideoElement
HTMLVideoElementはHTMLElementを継承したオブジェクトです。
videoタグに相当し、動画の制御をJavaScriptでできます。
See the Pen video by teradonburi (@teradonburi) on CodePen.
LocalStorage
localStorageを使うとブラウザにデータを半永続的に保存することができます(ドメイン単位)localStorage.setItem(key, data)
でデータを保存することができます。
JavaScriptをオブジェクトを直接保存することができないので文字列(JSON文字列)に変換しています。
JSON形式に変換するにはJSON.stringify
を使います。
保存したデータを取得するにはlocalStorage.getItem(key)
を使います。
取得したデータがJSON文字列の場合、JSON.parse
で文字列からJavaScriptオブジェクトに変換できます。
一度保存されたデータはブラウザをリロードしてもブラウザに残り続けます。
明示的にlocalStroageのデータを消すには、localStorage.removeItem(key)
を使います。
See the Pen localStorage by teradonburi (@teradonburi) on CodePen.
Fileオブジェクト
File APIを使うとユーザがアップロードしたファイルの操作をブラウザ上で直接取り扱うことができます。
よく使う例として、画像ファイルをinputタグからアップロードしたとき、Fileオブジェクトとして格納されて取得できます。
取得したファイルのファイル名、MIMEタイプなどを取得できます。URL.createObjectURL
を使うとFileオブジェクトを一時的なURLとして変換することができます。
(このURLはimgタグ、audioタグ、videoタグなどのsrcとして指定することができます。)
See the Pen File API by teradonburi (@teradonburi) on CodePen.
もうちょっと複雑な例は以下が参考になります。
参考:JavaScript で File API を使用してファイルを読み取る
FormDataオブジェクト
JavaScriptでフォームデータが正しいものが入力されているかチェック(validate)する制御を送信前に行うことができます。
FormDataオブジェクトを使うことで入力されたFormのデータを参照したり、JavaScript側で追加したりできます。
JavaScriptでのデータ通信にはXHR(XMLHTTPRequest)もしくはFetch APIを使って行われることが一般的です。
または、XHRをラップしたライブラリaxiosを使う方法などがあります。
See the Pen FormData by teradonburi (@teradonburi) on CodePen.
アップロードする先のサーバが必要ですが、
glitchというサービスを使うことで簡易的にNodeJSのサーバを立てています。
以下、サーバ側の実装です。
constexpress=require('express')constapp=express()constmulter=require('multer')constcors=require('cors')constupload=multer({dest:'uploads/'})// APIエラーハンドリングするためのwrapperconstwrap=(fn)=>(req,res,next)=>fn(req,res,next).catch(err=>{console.error(err)if(!res.headersSent){res.status(500).json({message:'Internal Server Error'})}})// エラーハンドリングprocess.on('uncaughtException',(err)=>console.error(err))process.on('unhandledRejection',(err)=>console.error(err))process.on('SIGINT',()=>process.exit(1))// CORS(別ドメインからの通信を許可する)app.use(cors())// publicフォルダapp.use(express.static('public'))// POSTデータを取得するためのミドルウェアconstbodyParser=require('body-parser')app.use(bodyParser.urlencoded({extended:true}))app.use(bodyParser.json())// アップロードAPIapp.post('/api/upload',upload.single('image'),wrap(async(req,res)=>{console.log(req.body)console.log(req.file)res.json({image:req.file,...req.body})}))// サーバ起動app.listen(process.env.PORT,()=>{console.log('server started')})
今回はファイル送信があったため、バックエンドを実装しましたが、
JSONデータを返す、APIサーバのモックであれば、json-serverを使うとさらに簡単にモックサーバの作成ができます。
WebRTC
WebRTC(Web realTime Communication)のことでリアルタイムビデオチャットをブラウザで行うための機能です。
getUserMediaによるカメラからのリアルタイム動画取得とWebSocketによるPeerConnection通信により実現されています。
カメラからの動画取得のサンプルはこちら
参考:「MediaDevices.getUserMedia() 」について
WebSocketに関してはSocket.ioというライブラリを使うのが一般的です。
ビデオ会議のサンプル:Socket.io | WebRTC One-to-One Video Chat
Canvas, WebGL
Canvasを使うことで独自の画像処理やDOMを画像化するなどといった特殊なこともできます。
参考:Canvasを用いた9つの画像処理フィルターとそのアルゴリズムの解説
See the Pen canvas by teradonburi (@teradonburi) on CodePen.
DOMを画像化する方法は直接実装するよりhtml2canvasを使ってしまったほうが手っ取り早いです。
WebGLに関しては、本格的な3Dをウェブ上で表現するための技術です。
初期化にはCanvasの延長上でwebglのcontextを取得する必要があります。
参考:WebGL 入門
数学的な計算(ベクトル、行列)の知識が必要なのとシェーダー等やれることが多すぎるのと仕様がかなり頻繁に更新され、
直接扱うのはかなり大変なため、
Three.jsやA-Frameなどのライブラリを使うことが多いです。
頑張れば、本格的な3Dゲームもブラウザ上で実現可能です。(もちろんパソコンのスペックも必要ですが・・・)
参考までに以前作ったものを上げておきます。
Web Animation API
Web Animation APIを使うとCSS3のキーフレームアニメーションをJavaScriptで行うことができます。
(ただし実験的な機能なため、まだ動かないブラウザが多いので実プロダクトでは使えません。)
See the Pen Web Animation API by teradonburi (@teradonburi) on CodePen.
スクロールアニメーション
Vanilla JSで直接実装するのが大変なものにスクロールアニメーションがあります。
クリックしたら指定のアンカーリンクまでスクロールアニメーションするといった挙動です。
smooth-scrollというライブラリを使うとあっさり実装できます。
参考:Vanilla.jsのアニメーションスクロールプラグイン「Smooth Scroll」
See the Pen Smooth Scroll by teradonburi (@teradonburi) on CodePen.
パララックス
スクロールアニメーション同様Valilla JSで表現するのが厄介なのが、パララックスです。
これは、スクロールに連動してHTML要素がアニメーションすることです。
こちらもrellaxというライブラリを使えば比較的簡単に実現できます。
See the Pen Rellax by teradonburi (@teradonburi) on CodePen.
まとめ
Webフロントエンドの基礎的な部分に関して説明しました。
さらにWebフロントエンドに対する知識と理解を深めるには次のものを勉強すると良いと思います
また、実践でプロダクトを作りながら覚えていくと良いでしょう。
拙書ですが、グロースハックの記事を書きました。(宣伝)
note:スタートアップ界隈4年目エンジニアが苦労したグロースハック手法について語る
kindle版:スタートアップで知っておきたい知識・グロースハック手法入門
内容はほぼ同じです。
はじめに
この記事は以前私が投稿した記事の続編となります。合わせて読んで頂けると嬉しいです
Vueを扱えるようになりたいけどJavaScript書いたことがなかったので、JavaScriptとVueを同時に勉強する。
今回は、前回のコードを改修〜見た目実装までの手順を記載しました!
完成品はこちらとなります
前回のコードを改修
まずは前回のコードの手直しから始めましょう。
前回の記事で改修案のコメントをくださった方ありがとうございます。
参考にさせていただきながら、進めていきたいと思います!
前回のコードはこちら
<template><div><p>じゃんけん!</p><button@click='guu'>グー</button><button@click='tyoki'>チョキ</button><button@click='paa'>パー</button><p>わたしは{{watashi}}</p><p>あいては{{aite}}</p><p>この勝負…{{result}}</p></div></template><script>exportdefault{name:'Game',data(){return{watashi:'',watashi_hand:'',aite:'',aite_hand:'',result:''}},methods:{guu(){this.watashi='グー'this.watashi_hand=0this.aite_no_te()this.syouhai()},tyoki(){this.watashi='チョキ'this.watashi_hand=1this.aite_no_te()this.syouhai()},paa(){this.watashi='パー'this.watashi_hand=2this.aite_no_te()this.syouhai()},aite_no_te(){switch(Math.floor(Math.random()*3)){case0:this.aite='グー'this.aite_hand=0breakcase1:this.aite='チョキ'this.aite_hand=1breakcase2:this.aite='パー'this.aite_hand=2break}},syouhai(){switch(((this.watashi_hand-this.aite_hand+3)%3)){case0:this.result='引き分けっ'breakcase1:this.result='あなたの負け…'breakcase2:this.result='あなたの勝ち!'break}}}}</script>
この後、見た目を実装するために画像を挿入したりするので、そもそも必要のない部分が出てきます。
その部分に関しては改修の余地があっても手直しせずに削除し、残す部分だけ手を加えていきます。
改修後はこちら
<template><div><p>じゃんけん!</p><buttonv-for="item in shapes":key="item.key"@click="select(item.key)">{{item.label}}</button><p>この勝負…{{resultText}}</p></div></template><script>exportdefault{name:'Game',data(){return{shapes:[{label:'グー',key:0},{label:'チョキ',key:1},{label:'パー',key:2}],resultText:'',player:'',bot:''}},methods:{select(key){this.player=keythis.result()},result(){this.bot=Math.floor(Math.random()*3)switch(((this.player-this.bot+3)%3)){case0:this.resultText='引き分けっ'breakcase1:this.resultText='あなたの負け…'breakcase2:this.resultText='あなたの勝ち!'break}}}}</script>
解説していきます。watashi
とaite
に関しては画像やボタンで手がわかるように表現したいので、結果的にいらなくなるため消しました。
グー、チョキ、パーとそれに関連した数字を今まではmethods
内にその都度書いていましたが、これをdata
内に一箇所にまとめます。
data(){return{shapes:[{label:'グー',key:0},{label:'チョキ',key:1},{label:'パー',key:2}],...
グーの場合は0というふうに既に決まっているので、配列にまとめることができました。これでいちいちグー
とか=0
とか書かなくてよくなりました。
今度はボタンの部分を見ていきます。
<button@click='guu'>グー</button><button@click='tyoki'>チョキ</button><button@click='paa'>パー</button>
私はボタンタグを三つ配置していましたが、こちらはfor
文を使う事でボタンタグを一つにすることができます。
<buttonv-for="item in shapes":key="item.key"@click="select(item.key)">
{{ item.label }}
</button>
こうですね。
さらにfor
文を使用し@click="select(item.key)"
となったことで、クリック時の関数も一つにすることができます。
guu(){this.watashi='グー'this.watashi_hand=0this.aite_no_te()this.syouhai()},tyoki(){this.watashi='チョキ'this.watashi_hand=1this.aite_no_te()this.syouhai()},paa(){this.watashi='パー'this.watashi_hand=2this.aite_no_te()this.syouhai()},
三つもあった関数が記述が
select(key){this.player=keythis.result()},
これ一つだけになります。syouhai
はダサいのでresult
に名前を変更。watashi_hand
もダサいのでplayer
に名前を変更。 aite_no_te()
の処理はbot
に名前を変えつつresult
内に移動させます。
result(){this.bot=Math.floor(Math.random()*3)switch(((this.player-this.bot+3)%3)){case0:this.resultText='引き分けっ'breakcase1:this.resultText='あなたの負け…'breakcase2:this.resultText='あなたの勝ち!'break}},
this.bot
ってせずにswicth
文の中に直接Math.floor(Math.random() * 3)
を書いてもいいんですが、画像の出しわけでthis.bot
は使いたいのでこういう書き方をしています。
画像の挿入とアニメーションの実装
さて、現時点では相手の手が表示されない為わからず、勝敗の結果しか表示されなくなっています。
今度は相手の手をグーチョキパー三つの画像で表示させていきます。
アニメーションの方法ですが、画像を配列に入れてそれを順番に表示って方法は既にされているかたがちらほら見かけてしまったので、
同じだとつまらなかったので私はcssで頑張っていきます。
まずはグーチョキパーの画像を用意しましょう。
私はフリー素材を拝借して色を塗りました。ちなみに、画像はsrc/assets/
に入れましょう。
シンプルに表示させます。画像もちょうどいいサイズにcssをいじっておきました。
<p>じゃんけん!</p><imgsrc="@/assets/rock.png"><imgsrc="@/assets/scissors.png"><imgsrc="@/assets/paper.png">
これをbot
に入る数字に合わせて表示を出しわけます。ついでにボタンの横ではなくて上に表示したいのでdiv
で囲います。
<div><imgv-if="this.bot === 0"src="@/assets/rock.png"><imgv-if="this.bot === 1"src="@/assets/scissors.png"><imgv-if="this.bot === 2"src="@/assets/paper.png"></div>
これでボタンをかちかちするとランダムに画像が一つだけ表示されるようになりました。
ボタンを押したあとはこれで問題ないのですが、ボタンを押すまでの間は画像をどぅるるるる(伝われ)ってしたいのでまずはボタン押す前と後で表示を出しわけましょう。
<divv-if="pon"><imgv-if="this.bot === 0"src="@/assets/rock.png"><imgv-if="this.bot === 1"src="@/assets/scissors.png"><imgv-if="this.bot === 2"src="@/assets/paper.png"></div><divv-else><imgsrc="@/assets/rock.png"><imgsrc="@/assets/scissors.png"><imgsrc="@/assets/paper.png"></div>
data(){return{shapes:[{label:'グー',key:0},{label:'チョキ',key:1},{label:'パー',key:2}],resultText:'',player:'',pon:false}},methods:{select(key){this.pon=truethis.player=keythis.result()},
ボタンを押す前と押した後で分けるためにpon
を実装しました。デフォルトではpon
はfalse
で、ボタンをクリックするとtrue
になりどれか一枚の画像が表示される仕組みです。
pon
がfalse
の時、3枚の画像をどぅるるると表示させたいのですが、これはcssのanimation
で実装してきます。
cssに下記の記述を追加して、各画像のclass
にanimation
を追加します。
<divv-else><imgclass="animation"src="@/assets/rock.png"><imgclass="animation"src="@/assets/scissors.png"><imgclass="animation"src="@/assets/paper.png"></div>
.animation{animation-name:img;animation-duration:0.3s;animation-iteration-count:infinite;opacity:0;}@keyframesimg{0%{opacity:0;}25%{opacity:1;}50%{opacity:0;}}
こんな感じ。
画像が出たり消えたりしていますね。
次は各画像にdelay
をかけて表示するタイミングをずらして、3枚の画像を重ねます。
<divclass="img-area"><divv-if="pon">
...
</div><divv-else><imgclass="animation"src="@/assets/rock.png"><imgclass="animation scissors"src="@/assets/scissors.png"><imgclass="animation paper"src="@/assets/paper.png"></div></div>
.img-area{position:relative;margin-bottom:10px;}.animation.scissors{position:absolute;top:0;left:45%;animation-delay:0.1s;}.animation.paper{position:absolute;top:0;left:45%;animation-delay:0.2s;}
完璧ですね。GIFなんでちょっと違和感ありますが、実際だと綺麗にどぅるるるしてくれてます
ここでちょっと機能追加
じゃんけんをやり直すには、現状画面をリロードするしかなく不便なので「もう一度!」ボタンを実装します。
<button@click="retry">もう一度!</button>
retry(){this.pon=falsethis.resultText=''this.player=''},
これでok。retry()
でdeta
内を最初の状態に戻しています。
Bootstrapを使ってデザインを良くする
あとやりたい事は、
①ボタン周りのデザインをかっちょよくしたい
②ボタンをクリックした時に、色を変えるなどして何のボタンをクリックしたかわかりやすくしたい
この2点です。どちらもBootstrap
でちゃちゃっとできちゃいますので実装しちゃいます。Bootstrap
の適用方法・使い方に関してはここで説明すると長くなると思い、別で記事を作成しましたので興味がある方は参考にしてください。
Vue.jsにBootstrapを適用させる方法
こちらの公式ページのテンプレートを使用します。
https://bootstrap-vue.js.org/
<div><b-button>
:pressed.sync="item.state" variant="outline-success"
v-for="item in shapes" :key="item.key"
@click="select(item.key)">
{{ item.label }}
</b-button></div><b-buttonvariant="outline-danger"@click="retry">もう一度!</b-button>
ボタンがクリックされたらstateがtrueになり、色が緑色のままになるようにしました。
また、shapesにもデフォルトでstateがfalseになるように記述を追加しています。
ついでに全体的なcssをちょいちょいと調整します。
vueのlogoは、「vueで作ったよ!」って事が一目でわかるので残しておきました。ちょっとデカかったのでサイズはいじりましたが
完成コードはこちら
<template><div><p>じゃんけん!</p><divclass="img-area"><divv-if="pon"><imgv-if="this.bot === 0"src="@/assets/rock.png"><imgv-if="this.bot === 1"src="@/assets/scissors.png"><imgv-if="this.bot === 2"src="@/assets/paper.png"></div><divv-else><imgclass="animation"src="@/assets/rock.png"><imgclass="animation scissors"src="@/assets/scissors.png"><imgclass="animation paper"src="@/assets/paper.png"></div></div><div><b-button:pressed.sync="item.state"variant="outline-success"v-for="item in shapes":key="item.key"@click="select(item.key)">{{item.label}}</b-button></div><b-buttonvariant="outline-danger"@click="retry">もう一度!</b-button><div>この勝負…<br/><spanclass="text">{{resultText}}</span></div></div></template><script>exportdefault{name:'Game',data(){return{resultText:'',player:'',pon:false,shapes:[{label:'グー',key:0,state:false},{label:'チョキ',key:1,state:false},{label:'パー',key:2,state:false}]}},methods:{select(key){this.pon=truethis.player=keythis.result()},result(){this.bot=Math.floor(Math.random()*3)switch(((this.player-this.bot+3)%3)){case0:this.resultText='引き分けっ'breakcase1:this.resultText='あなたの負け…'breakcase2:this.resultText='あなたの勝ち!'break}},retry(){this.pon=falsethis.resultText=''this.player=''this.shapes=[{label:'グー',key:0,state:false},{label:'チョキ',key:1,state:false},{label:'パー',key:2,state:false}]}}}</script><stylescoped>button{margin:10px5px;box-shadow:none!important;}img{width:10%;}.animation{animation-name:img;animation-duration:0.3s;animation-iteration-count:infinite;opacity:0;}.animation.scissors{position:absolute;top:0;left:45%;animation-delay:0.1s;}.animation.paper{position:absolute;top:0;left:45%;animation-delay:0.2s;}.img-area{position:relative;margin-bottom:10px;}.text{font-size:50px;}@keyframesimg{0%{opacity:0;}25%{opacity:1;}50%{opacity:0;}}</style>
画像周りとか、retry()とかdata()とか、もっときれいに短く書けそうな気がします…
勝敗結果を保存して戦歴表示とかも…
でも、やりたかったことができて一旦キリがいいのでここでおしまいにします。
さいごに
ここまで読んでくださってありがとうございました。
どなたかの参考になれば嬉しいです!
誤字脱字・発信した情報に間違い等ございましたら、指摘して頂けますと幸いです
また、説明にわかりづらい点がございましたら、改善致しますのでぜひコメントください
子要素が全てfloatの時の、親要素の高さ
通常、親要素の高さは子要素を包む高さとなるが、子要素が全てfloatの時、親要素の高さは0となってしまうという性質がある。
float は浮いているという意味で、親要素からみると float の子要素は存在しないように見えるからである。
例
<!DOCTYPE html><htmllang="ja"><head><metacharset="utf-8"><title></title><linkrel="stylesheet"href="css/reset.css"><linkrel="stylesheet"href="css/style.css"></head><body><headerclass="header"></header><divclass="wrapper"><mainclass="main"></main><divclass="sidemenu"></div></div><footerclass="footer"></footer></body></html>
.header{width:100%;/* border: 1px solid red; */}.wrapper{width:970px;/* border: 1px solid red; */margin:30pxauto40px;}.main{display:block;float:left;width:660px;}.sidemenu{float:right;width:275px;}.footer{width:100%;}.header,.main,.sidemenu,.footer{border:1pxsolid#aaa;background-color:#ccc;}.header,.footer{height:100px;}.main,.sidemenu{height:500px;}
mainクラスとsidemenuクラスにはそれぞれfloatが指定されているため高さを認識できなくなり、footerが上がってしまう。
改善策
親要素にclearfix
クラスみたいにクラス名をつける(使いまわせるように)。
<divclass="wrapper clearfix"><mainclass="main"></main><divclass="sidemenu"></div></div>
擬似要素を使用しclear: both;
とし(もしくは 'clear: left;')、floatを解除することで、高さを認識できるようになり、この問題を解決することができる。
https://saruwakakun.com/html-css/basic/before-after
.clearfix::after{content:'';display:block;clear:both;}
webプログラミング言語とは?
webプログラミング言語は、webサービスにおいて自分のアイデアを形にしたり、みんなに使ってもらったりするための言語です。
大きく分けるとフロントエンドとバックエンドの2つに分類することができます。
フロントエンドとは
フロントエンドとは、ブラウザに働きかけるもので、簡単に言うと「見せる」モノです。ホームページやブログなど目に見える部分を担当する言語です。サイトに装飾や動きを与えるなど目に見えて自分が作成したプログラムが反映されていくので自分はやっていて楽しいです。(笑)
フロントエンドの言語
- HTML
- CSS
- Javascript
- jQuery
ホームページやブログは、HTML、CSSのみで作ることが可能であり、サイトに動きを付けたい場合にJavascriptやJQueryを用います。
バックエンドとは
バックエンドとは、サーバ内で動く仕組みなどのことで、私たちの目には見えないとことで働くモノです。また、バックエンドのことをサーバーサイドと言い換えることもできます。サーバーサイドの言語は、目に触れる部分ではなくアプリやサービスの内部を担当する言語です。
バックエンドの言語
- PHP
- MySQL
- WordPress
フロントエンドに興味を持ったあなたに
私は、ホームページなどウェブサイト制作に興味があったのでフロントエンドを中心に現在勉強をしています。そのようなこともありフロントエンドを始めるにあたって使いやすいおすすめの環境を記載します。
プログラミングを始めるためには、まずエディタを用意をする必要があります。
おすすめのエディタ
エディタとは、一言でいうとプログラムを書くためのソフトです。自分が「使いやすい!」と思い、おすすめするエディタは、「Visual Studio Code」です。VScodeは、補完機能が充実しているので文法ミスも少なくなり、初心者の方にお勧めです。
以下のURLからダウンロード可能です。
[https://code.visualstudio.com/]
フロントエンドは、エディタでプログラムを書き、ブラウザで動作を確認する形になります。
とりあえずやってみよう!
自分がwebプログラミングを始めたのは、友達の「一緒にHTMLの勉強しよ!」という一言がきっけでした。自分のやりたいことが見つかっていなかった私は、とりあえず勉強してみることにしました。そこから徐々にwebプログラミングの面白さに気づいていきました。
挑戦することで視野が広がることを実感しました
フロントエンドとバックエンドのどちらか自分が興味を持つほうから勉強を始めていくことをお勧めします!
パンくずリストとは
[メルカリより]https://www.mercari.com/jp/guide/car/transport_guide/
こういうのとか
[Web Design Trendsより]https://webdesign-trends.net/entry/2310
こういうのをパンくずリストという
名前の由来
童話「ヘンゼルとグレーテル」からきているとのこと。
パンくずリストを作ろう
<!DOCTYPE html><htmllang="ja"><head><metacharset="utf-8"><title>パンくずリスト</title><linkrel="stylesheet"href="css/bread-crumbs.css"></head><body><divclass="bread-crumbs"><ul><li><ahref="#">ホーム</a></li><li><ahref="#">カテゴリー1</a></li><li><ahref="#">カテゴリー2</a></li><li>カテゴリー3
</li></ul></div></body></html>
body{margin:0;}.bread-crumbsul{list-style:none;text-decoration:none;padding:0;margin:10px10px;}.bread-crumbsli{display:inline;}.bread-crumbsli:after{content:'>';color:#000000;}.bread-crumbsli:last-child:after{content:none;}.bread-crumbslia{text-decoration:none;color:#218b21;}.bread-crumbslia:hover{text-decoration:underline;}
疑似要素を使って>を表示していますが、下の記述がないと一番右側にも>が表示されてしまいます。
やっていることは一番後ろのli要素の疑似要素は無し(非表示)ということです。
.bread-crumbs li:last-child:after {
content: none;
}
パンくずリストを作るのは別にli要素じゃなくてもいいのでは?と思ったのですが、Googleではli要素を推奨しています。
https://developers.google.com/search/docs/data-types/breadcrumb