20191205のHTMLに関する記事は14件です。

web入門(1) ~HTML入門~

必要なもの

・Chrome

・VScode

それぞれChrome、VScodeで検索するとサイトが出てくるのでそこでダウンロードをしてください

はじめに

HTMLとはWebページを作成するための言語です。普段、皆さんが閲覧するWebページのほとんどはHTMLで作られています。HTMLはテキストをタグ付けしていき、ブラウザ(Chrome)などに読み込ませて動作させます。以下、例を挙げましょう。

sample.html
    <h1>HTML第一回</h1>
    <h2>プログラミング、始めました</h2>
    <h3>よろしくお願いします</h3>

h1などのhとは見出し(heading)を表し、後ろの数字で重要度(大きさ)を表します。こちらを動作させると、下のように表示されます。

img2.PNG

<どんなふうに表示させるか> 表示させたい文 </どんなふうに表示させるか>

といった形です。

では実際に皆さんで実践してみましょう。

HTMLの基本的な書き方

まずVisual Studio Codeを起動してください。左上の「ファイル」から「新規ファイル」を選択しましょう。このままHTMLを書き込んでもいいのですが、先に左上の「ファイル」から「名前を付けて保存」を選択し、ファイル名を「sample.html」として適当な場所(デスクトップがおすすめ)にHTMLファイルとして保存しましょう。(エディタ側では(ここではVisual Studio Code)まだ何についてのファイルか分からないため)
img6.PNG
img7.PNG
img5.PNG

Visual Studio Codeに戻って以下のような文章を打ちましょう。エディタ側はHTMLファイルだと認識してくれたので、自動で色を振り分けてくれると思います。終了タグには 「/」 (スラッシュ)のつけ忘れに気を付けましょう。

sample.html
<h1>HTML第一回</h1>
<h2>プログラミング、始めました</h2>
<h3>よろしくお願いします</h3>

では動作させてみましょう。ファイルを保存して(Ctrl + S)、Chromeで開きましょう。皆さんが作成したsample.htmlをダブルクリックしてください。

img8.PNG
※もしdemo.htmlが上のようなアイコンになっていない場合は、Chromeが既定のブラウザになっていません。詳しくは以下のリンクを参照してください。
[https://support.google.com/chrome/answer/95417?co=GENIE.Platform%3DDesktop&hl=ja]

上手く表示されましたか?このようにHTMLを使えば簡単にWebページを作ることができます。

ではHTMLの構造について解説します。少しレベルアップしますが、頑張りましょう。HTMLとは基本的に以下のような入れ子構造で記述します。

sample.html
<!DOCTYPE html>
<html>
<head>
  <title>ここがタイトル</title>
</head>
<body>
 <h1>HTML第一回</h1>
 <h2>プログラミング、始めました</h2>
 <h3>よろしくお願いします</h3>
</body>
</html>

img9.PNG

上の画像を大雑把に説明すると<html>という大きなタグの中に<head>(設定、ページ上には表示されない)<body>(ページ上に表示される内容)が入っているという構造です。
先ほど記述した<h1>~~~</h1>などはbody要素に書くものだったのですね。このようにHTMLは各タグを入れ子にして記述していくので、コードが見やすくなるよう、インデント(字下げ)をしましょう。

これでHTMLの基本的な書き方や知識を学べました。次に様々なタグを具体的に紹介していきたいと思います。

タグについて

今度は様々なタグを使ってHTMLを記述してみます。先ほど書いたコードの内容と下の図を思い出しながら、覚えていきましょう。

img9.PNG

<head>~</head>の中に記述するもの

<meta>
<meta>タグは文書に関するデータを指定します。終了タグは必要ないので注意しましょう。
以下文字コードを指定した例
<meta charset="UTF-8">
<title>
タイトルタグで文字を挟むとその文字がタイトルになります。

<title>ここがタイトル</title>
img10.PNG
<link>
タグは外部ファイルを指定して読み込ませます。終了タグは必要ないので注意しましょう。
以下CSSファイル(style.css 後々やります)を読み込ませた例
<link rel="stylesheet"href="style.css">

<body>~</body>の中に記述するもの

<h〇></h〇>

<h1>見出しを表す、一番重要</h1>
<h2>二番目に重要な見出し</h2>
<h3>三番目に重要な見出し</h3>

img12.PNG

h1~h6まであります。見出しを表すタグなので、単純に大きい文字を表示するために使うのはやめましょう。

<p></p>

<p>pタグには主に本文や説明文を入れる</p>

img13.PNG

pはパラグラフの略です

<div></div>
div要素そのものに特別な意味はなく、単純に要素をまとめるために使う。

<div>
  <p>こうやって</p>
  <p>pタグをまとめた</p>
</div>

img14.PNG

<a></a>
aはアンカーを表し、Webサイトのリンクを貼る。

<a href="https://www.google.com">グーグルのリンク先</a>

img15.PNG

<img>
<img>は画像を表示する際に使用します。終了タグは必要ありません。

<p>サンプル画像です</p>
<img src="img/sample.PNG">

img16.PNG

きちんと画像が表示されましたね。

ところで、このimgタグの中のsrc="img/sample.PNG" や先ほどのaタグのなかのhref=”https://www.google.com” とは何なのでしょうか?

結論から言うとこれはimgタグの中のscr属性、aタグのなかのhref属性を指定しいる文です。
何を言っているのかわからないと思いますので、まずは”属性”について説明をします。
属性とは感覚的に言うと要素に ”詳細設定をつけるようなもの” と思ってください。
例えば先ほどの 

<a href="https://www.google.com">は
 a の href(参照するurl) は https://www.google.com です。

ということを意味し、
また、

<img  src="img/sample.PNG"> とは
 img の scr(画像の場所) は img/sample.PNGです。

といった感じです。

基本的に<○○の □□は="△△です">という感じで大丈夫です。

ここまで基本なタグを一通り紹介してきました。では、ここで一度演習をしてみましょう。以下の基本構造を使って各々自由にサイトを作ってみてください。
※画像を使う場合はHTMLファイルと同じ場所に画像を保存してください。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>タイトル</title>
  </head>
  <body>
    ページの内容(ここを自分で書いてみましょう)
  </body>
</html>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

htmlをReactコンポーネントにぶちこんでやるぜ〜〜!!

はじめに

いなたつアドカレの五日目の記事です。

今回はReactで生のhtmlを扱うための方法とその時の注意について少し、、、

ざっくりいうと

  • dangerouslySetInnerHTMLを使おう
  • XSS に気をつけよう
  • markdownから変換して表示も可能だよ

dangerouslySetInnerHTMLを使う

<span dangerouslySetInnerHTML={{ __html: html}} />

dangerouslySetInnerHTML属性に__html(あんだーばーあんだーばーへいちてぃーえむえる)に展開したいhtmlを設定する オブジェクト を渡すことで指定したhtmlをタグ内部に展開することができます。

dangerouslyやねん

XSSの危険がつきまとってくるんですよね。

XSSってのはクロスサイトスクリプティングといって、テキストボックスにhtmlを埋め込み、予期せぬ動作をさせようとすることです。

これの何がdangerouslyかというと
- テキストボックスにスクリプトを入力し、javascriptを実行させることで、クッキーなどを盗みなりすましができる
- 同様に、アプリケーションの機能を悪用されるかもしれない
クッキーでセッションIDなんかを保持しているとなりすましの温床になりかねないですね。。。。
dangerouslyって名前についてるのはこういうところからなので、まあ、あまり使わない方がいいですね。

じゃあどーやって対策すんの

** サニタイズ **

markdownがうんぬんかんぬん

markdownを生のhtmlに変換してここにぶちこんでやるぜーしたらmarkdownエディタのプレビューっぽいことできるって話
次回reactとmarkedのお話を書きます。。。。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初心者によるプログラミング学習ログ 177日目

100日チャレンジの177日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

177日目は

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Web入門(2)

はじめに

CSSは一言でいうと、Webサイト上の文字・枠・背景などの見た目やそれらの配置を指定するための言語です。最初は「CSS は見栄えを変えることができるんだ」くらいの認識で構いません。CSS は HTML と合わせて用います。ちなみに CSS はCascading Style Sheetsの略です。

書き方

CSS を用いてスタイルを指定する際には、まずどこをどのような見た目に変更するか決めます。

sample.css
p { font-size : 40px; }

CSS の基本的な書き方は セレクタ {プロパティ名:値;} という構造になっています。セレクタには変更したい要素の名前を指定します。上の例ではp要素となっています。プロパティ名にはスタイルの種類を指定します。プロパティとは変更するスタイルの種類みたいなものです。例では文字の大きさとなっています。値にはプロパティをどのように変更するかを指定します。上の例では40pxとなっています。

一度に複数のプロパティを指定することもできます。その際、改行をしてもスタイルには影響がでません。コードが見やすくなるので、個人的には改行して書くことをおススメします。

sample.css
/* 改行しない*/
p { font-size : 30px; color: red; height : 80px; }

/*改行した*/
p {
   font-size: 30px;
   color: red;
   height: 80px;
}

基本的なプロパティとその使用例

基本的なプロパティ一覧

プロパティ 説明
width 横幅の指定
height 高さの指定
color 文字の色の指定
background 背景関係をまとめて指定
background-color 背景の色を指定
margin 要素外の間隔の指定(余白のようなもの)
padding 要素内の間隔の指定(余白のようなもの)
font フォント関係をまとめて指定
font-size フォントの大きさ(文字の大きさ)を指定
font-family フォントの種類の指定
float 要素を左右に寄せる

使用例

以下の sample.html を用意しました。(比較し易くなるように予めbackground-colorに黄色を指定しています。)

sample.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Sample</title>
    <link rel="stylesheet" href="sample.css">
</head>
<body>
    <p>こんにちは!</p>
</body>
</html>

tempsnip1.png

このWebページに以下のCSSを適用させてみます。

sample.css
/*背景を黄色、横幅を100px、高さを30pxにして、padding,marginを100px加える*/
p {
   width: 100px;
   height: 30px;
   padding: 100px;
   margin: 100px;
   background-color: yellow;
} 

tem2.png
Webページが変化しました!
ここで、「margin」と「padding」の違いについて軽く触れておきます。
上のプロパティ一覧表にも書いてありますが、「margin」は要素外、「padding」は要素内に余白を追加します。下図のようなイメージです。
tem.png

次にfloatを適用させてみます。

sample.css
/*p要素を右に寄せ、さらに背景を青色に変更*/
p {
   width: 100px;
   height: 30px;
   padding: 100px;
   margin: 100px;
   background-color: yellow;
/*要素を右に配置*/
   float: right;
}

tem3.png
要素が右に移動しました!

まとめ

  • CSS は HTMLで記述した要素のスタイルを指定するための言語である。
  • 「margin」は要素外、「padding」は要素内に余白を加える。
  • floatプロパティを用いると要素を左右に移動させることができる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FileAPIを使って、CSVファイルからテーブルを作成する方法

はじめに

初めまして、初投稿です。読みづらい箇所もあると思いますが、よろしくお願いします。
エクセルなどで作成した表データをそのままテーブルにできないかと色々模索した際に作成したコードです。
「エクセルをそのままテーブルにしたい!」という私みたいなモノグサさんのお役に立てれば幸いです。

環境

  • html
  • Javascript
  • Google Chrome
  • CSVファイル(Excel、Googleスプレッドシートなどで作成)
    ※条件:セル内改行なし ・ コンマ , は使用しない

作業手順

以下の手順でコードを作成していきます。
- 1. 【HTML】CSVファイルの読み込み
- 2. 【HTML】テーブルを書き出す場所を作成する
- 3. 【Javascript】form要素(CSVファイル)の取得する
- 4. 【Javascript】CSVの各データを配列として読み込む-1
- 5. 【Javascript】CSVの各データを配列として読み込む-2
- 6. 【Javascript】テーブルに書き出す処理
- 7. 【Javascript】作成したテーブルの tr にidを付与する

1 【HTML】FileAPIを使ってCSVファイルを読み込む

まず最初に、FileAPIを使ってCSVファイルを読み込みます。
accept="text/csv" とすることで、CSVファイルだけが選択できるようにします。

sakusaku_table.html
<input name="userFile" type="file" accept="text/csv">

2 【HTML】テーブルを書き出す場所を作成する

テーブルを書き出したい場所に、次のコードを入れます。
div id="table" に、テーブルが出力されます。

sakusaku_table.html
    <div class="container">
        <div id="table" class="userTableBox">     
      </div> 

3 【Javascript】form要素(CSVファイルの中身)の取得する

form要素を取得し、FileReaderクラスでFile オブジェクト(CSV)の中身を読み込みます。

sakusaku_table.js
    var form = document.forms.userform;
    form.userFile.addEventListener('change', function(e) {
    var result = e.target.files[0];
    var reader = new FileReader();
    reader.readAsText( result );

4 【Javascript】CSVの各データを配列として読み込む-1

3 で読み込んだCSVを配列化して取得します。
さらに、テーブルにした時の、1列の要素数を取得しておきます。

sakusaku_table.js
//1行ごとに配列化します。
    reader.addEventListener('load', function() {
    var arr = reader.result.split('\n'); 

//全ての配列を個別に取得します。
    for(i = 0; i < arr.length; i++){
      var arrayElements = new Array(arr[i]);
      } 

//一番上にくる配列(<th>タグに入る)を取得
      var first = arr[0];
      var userData = reader.result.split(/,|;|\n/);

//1列の要素数を取得
      var rowCnt = parseInt(userData.length) / parseInt(arr.length);

5 【Javascript】CSVの各データを配列として読み込む-2

配列データを中身の要素数(エクセルの列数)で均等に分割します。

sakusaku_table.js
      Array.prototype.divide = function(n){
        var userArray = this;
        var indx = 0;
        var results = [];
        var length = userArray.length;

        while (indx + n < length){
            var result = userArray.slice(indx,indx+n);
            results.push(result);
            indx = indx + n
        }

        var rest = userArray.slice(indx,length+1);
        results.push(rest);
        return results;
    }

    userArray = reader.result.split(/,|;|\n/);
    dividedArrayData = userArray.divide(rowCnt);

6 【Javascript】テーブルに書き出す処理

ここでついに、取り込んだCSVファイルのデータをテーブルに書き出します。この時点では、ヘッダー行のみ背景色と文字色を変更しておきます。さらに今後、CSSで見た目を修正する時のために各セルにIdとclassを追加する準備をします。

sakusaku_table.js
      function makeTable(data, tableId){
        var rows=[];
        var table = document.createElement("table");
//完成したテーブルに <table id="userCsvTable">というidを付与します。
        table.id = "userCsvTable" 

//(縦方向)の要素数を取得・縦方向の繰り返し処理回数を指定
        for(i = 0; i < data.length; i++){ 
         rows.push(table.insertRow(-1)); 
         if (i === arr.length){ 
          break
          }

//(横方向)の要素数を取得・横方向の繰り返し処理回数を指定 これは要素数分、列を作成する処理
        for(j = 0; j < data[0].length; j++){ 
         cell=rows[i].insertCell(-1); 
// 追加した行にセルを追加してテキストを書き込む
         cell.appendChild(document.createTextNode(data[i][j]));
         if(i==0){

// ヘッダー行(エクセルの、1行目):<th>の部分・背景色と文字色の指定
         cell.style.backgroundColor = "gray";
         cell.style.color = "white";

//ヘッダー行:各セルのidにインデックス番号を入れる
 //(ここでは0ゼロしか入らない・次のステップで正しい連番に置き換えます。)
         cell.id = i  

//各セルのclassを追加。ここではヘッダー行は index としています。
         cell.classList.add("index_"+i,"cellContents","header-cell"); 
         }
          else{
//ヘッダー行以外の内容行(エクセルの、2行目以降)
               cell.id = i  
//各セルのclassを追加。2行目以降(ヘッダー行以外)は contents としています。
               cell.classList.add("contents_"+i,"cellContents","body-cell")
                    }
                  }                    
          }

 // 指定したdiv要素にテーブルを追加する
          document.getElementById(tableId).appendChild(table);
          }

 // 表のデータ
          var data = dividedArrayData
// 表を作成する
          makeTable(data,"table");

7 【Javascript】作成したテーブルの<tr>にidを付与する

CSSで見た目を修正するために各セルに正式なidを付与して完成です。

sakusaku_table.js
 //作成したテーブルの tr にidを付与する
            var trId = "userElementID_"
            var tmp = document.getElementsByTagName("tr") ;

            for(var i=0;i<=arr.length-1;i++){
//id追加
                tmp[i].setAttribute("id",trId+i);
            }

//作成したテーブルの各セルにidを付与する ※⑥で先にセルにidを付与しないと動作しない 
          var idName = "cell_"
          var cellId = document.getElementsByClassName("cellContents") ;

          for(var i=0;i<=tmp.length-1;i++){
//idを追加
              cellId[i].setAttribute("id",idName+i);
          }

          }); 
        }); 

最後に

ここまでお付き合いいただきありがとうございます。
もっとシンプルな書き方とかあると思いますのでアドバイスなどいただけると嬉しいです。

動作サンプルはこちらからご確認いただけます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コーディングのTIPS

コーディングのTIPSを随時更新していきます。

・ホバー時の色は、カラーコードではなくopacity(透明度)をいじると良い

・基本的には要素同士の関係よりクラスで指定した方が良いが、
liとか、絶対にタグが変わらないものとかは関係でもOK

・タブレットで表示した時の見え方は、meta viewportでPC版に合わせる。そうするとタブレットの微妙な画面幅のことを考えなくて良くなる

・コーディングに入る前に、繰り返し使えそうなパーツは何かを考える

・余白はパーツのスタイルに入れず、利用箇所ごとで設定するとパーツの再利用性が上がる

・BEMの命名は、セクションごとではなくパーツごと
(ヘッダーにBlockが4個くらいあったりする)

・Block名はキャメルケースで少し長めにするとかぶる心配が減ってやりやすい

・flexboxで、カラム数を「2or4」みたいにしたい時は、要素を2つずつdivで囲む

・色は最初に定義しておくとやりやすい

・SMACSSの各セクションの開始位置に、エディターでしおりをつけておくと捗る

li:not(:last-child):not(:first-child)first-childlast-child以外という指定ができる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

HTMLにMarkdown組み込み

経緯

前提条件

社内の申請書やマニュアル類を探す際、ファイルサーバの階層の中から自力で探すか、ポータルサイトからExcelのリンク集(リンク切れまくる)開いて探すかしかなかった。

  • 僕は情報システム部門の人(htmlは嫌い)
  • クラウドは絶対許さないマン:lifter_tone1:な会社
  • IEで何でも動かす
  • ポータルサイトは社内ネットワークに接続時のみ

なぜMarkdownで作ろうと思ったか

  • Markdown超便利(普段HackMD使ってる)
  • 一般の人でもちょっと見たらわかる言語
  • メンテナンスなども誰でも簡単にできる

実際のHTML

加工してあるけど、概ねこんな感じ

html
<!DOCTYPE html>
<html lang="ja">
    <head>
       <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
       <title>title</title>
       <meta http-equiv="x-ua-compatible" content="IE11" >
       <meta http-equiv="x-ua-compatible" content="IE=EmulateIE11" >
       <link href="https://rawgithub.com/jasonm23/markdown-css-themes/gh-pages/markdown7.css" rel="stylesheet"></link>
   </head>
    <body>
        <div id="container">
        </div>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.5/marked.min.js"></script>
        <script>
var markdown = (function() {/*

# リンク集

## あれ関連

### あれする物体関連

| 分 類 | 帳票名 | 備考 |
|:---:|:---|:---|
| 帳票 | [filename](file:\\localsv\...) | あれの申請書 |
| マニュアル | [filename](file:\\localsv\...) | あれのマニュアル |

### あれするシステム関連

| 分 類 | 帳票名 | 備考 |
|:---:|:---|:---|
| 帳票 | [filename](file:\\localsv\...) | あれの申請書 |
| マニュアル | [filename](file:\\localsv\...) | あれのマニュアル |


*/}).toString().match(/\/\*([^]*)\*\//)[1];
           var md = marked(markdown);
           $("#container").append(md);
       </script>
    </body>
</html>

参照「HTML単体でMarkdownを表示させる」

やってみて

  • Markdownだからスッキリ(余計なことできないでいい)
  • たくさんウィンドウ開かないから少し画面がスッキリ!
    ブラウザ→エクスプローラー→Excel→PDFみたいなことがない
  • 分類ごとに申請書の一覧作ってリンク貼るだけだから簡単
  • 最新の通知や時期によって多い申請書を上部でリンク付けたり、別ページ作くったりしてもいいな。
    <a name="mobile_pc"></a>でジャンプ先作って、(#Win10)で飛べばいいし。

課題

  • IE以外のブラウザではfileリンクが開かないので、Webページで完結できるものはどんどんWebページにしていく。
  • IEじゃなかったら<details><summary>を使いたい。
  • 個人的にはCodiMDとか構築したいけど、それはまだ先になりそう…。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コーディングでハマったポイント

コーディングでハマったポイントを、随時更新していきます。

display: tableを持つ要素には、overflow: scrollが効かない
tabledisplay: blockを指定すると、widthが効かなくなる
→tableはdivで囲っておくのが無難

・classに対して:first-childnth-of-type()などを指定すると、特殊な動きをする

display:inline-blockを使うと、謎の余白が生まれることがある。
→親要素にfont-size: 0を指定すると解消。
(参考:inline-blockの隙間をなくす方法

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

よくある動き、お気に入りの実装方法

コーディングをする上でよく遭遇する動きの実装方法を、随時更新していこうと思います。

ハンバーガーメニュー

CSSで実装。表示の動きとか場所は、以下の記事よりもう少し工夫した方が良いかも。
CSSだけで簡単!ハンバーガーメニューの作り方(スマホ対応)

タブ切り替え

CSSで実装。
CSSだけでタブ切り替えを作る方法

画像スライダー

Swiperを使って実装。
【実例12パターン】画像スライダーはSwiper使っておけば間違いない!実用的な使い方を紹介

画像ポップアップ

これって方法が見つかってません。lightboxが有名だけど、何となくもっさりしていた印象があります。

グラフ

Chart.jsを使って実装。
Chart.jsでグラフを描画してみた

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CSSは神なのでゲームも作れる

はじめに

この記事はN高等学校 Advent Calendar 2019の12日目の記事です。
昨日の記事は同じキャンパスの先輩であるGenbu氏の静的な Web サイトをどうやって速くするかです。合わせて是非。
因みに明日の記事も同じキャンパスの狂人Nemesis氏のFlutterと云ふものを触った話を語りんすです。こちらも合わせてどうぞ。

こんにちは。N高等学校1年生のはとと申します。プログラミング歴は一年にも満たない若輩者ではありますが、ここまでの学習の成果としてアドベントカレンダーを書かせていただきます。よろしくお願いいたします。

作ったもの

See the Pen GRgJjZL by HATO (@hatopoppo) on CodePen.

タイピングゲームです。HTMLとCSSだけで実装しました。JavaScriptは使ってません。
inputの自動選択は、私が知る限りHTMLとCSSではどうにもならないので一々クリックしないといけない仕様となっております。
本来こんな事CSSでやるべきじゃないので当然の如く脳筋クソコードです。それにあいまって元々のクソコード力も重なりクソの二段構えコードとなっております。

若干ゃ解説

このコードの鍵や、苦労した点等の解説を少しだけします。

仕組み

まずこのタイピングゲームで鍵になるのはここ

CSSisGOD.html
<input type="text" class="A1" pattern="java" required>

inputタグの中の

CSSisGOD.html
pattern="java"

ここ。

このpatternという所でinputに入れられたテキストの正誤判定をしています。
本来の用途としては、

sample.html
pattern="^[0-9A-Za-z]+$"

等で受け付ける文字の種類を限定するのですが1、今回はここに文字列javaを入れることにより、この文字列以外は受け付けないという形に出来ました。

そして、文字列が正しいと判断されると擬似要素 :valid が、
正しくないと判断されると擬似要素 :invalid が与えられる為、CSSで

CSSisGOD.css
.A1:valid ~
.A2:invalid ~
.A3:invalid ~
.A4:invalid ~
.A5:invalid ~
.A6:invalid ~ .Q2 {
  opacity: 1;
}

のように書いてやって、A1(最初の問題のinput)が正しければ次の問題を表示という形に出来ました。
因みに得点の部分もこういう感じで切り替えています。本来は別の方法を使いたかったのですが後述の理由により断念しました。

苦労した点

今回苦労したのは、inputの切り替えと得点の兼ね合いです。
現在正解時のinputの交代は、

CSSisGOD.css
input[pattern]:valid{
  display: none;
}

このように、validの時に要素を消すという処理で行なっているのですが、このような形にすると、元々得点の部分で行なっていた、要素のカウントを出来るコード

sample.css
input[pattern]:valid{
counter-increment: count; 

が動かなくなり、原因と改善案の模索で半日ほど潰していました。
理由は恐らく、要素そのものを消している為、カウント対象の要素がなかった事だと思います。
実際、opacityを0にする方式にしてみるとしっかりと得点のカウントがされました。
しかし、opacityを切り替える場合では、inputが常に存在している状態になります。
その状態だと問題を解いた後も、見えないinputがまだ選択状態、即ち入力待ちの状態になってしまう為、そこから次のinputの選択をせずに入力を行うと

一問前のinputに入力
    ↓
patternの正誤判定が働き一問前の問題とinputがまた表示

というストレスフルの状態になった為、やむなくinputは消滅させ得点は正誤判定で切り替えるシステムとしました

終わりに

脳筋実装ではありますが、CSSでもゲームを作る事ができました。
CSSの限界はもっと上にあると思うので、今後もCSSの限界に挑み続けようと思います。
最後に、このゲームを作っている途中にクラスメートに言われた言葉を金言として書き、終わろうと思います。
「CSSはゲームを作るものじゃない」
「時間の無駄」
「JavaScript使え」
「CSS中毒」

ご覧いただきありがとうございました。

追記

すでにCSSで僕なんかよりも完成度高くタイピングゲームを作り、分かりやすく解説もしていらっしゃる先駆者の方がおりましたので、畏敬の念を込めてリンクを貼らせていただきます。
codegrid


  1. この場合は、半角英数字のみという制限をかけている。詳しくは他記事参照。 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Webを見ているときに起きていること

この記事はSmartHR Advent Calendar 2019 5日目の記事です。

はじめに

こんにちは、フロントエンドエンジニアの@cidermitainaです。

みなさん、Webを見ているときにブラウザで起きていることって考えたことありますか?
ちなみに私は考えたことがなかったです。。。

アドレスバーにURLを入力すると、すぐに見たいページが表示される、このことが当たり前だと思っていたのですが、実はブラウザの中では様々のことが起きているのです。

今回はそんなブラウザについての記事です。

アドレスバーにURLを入力してから起きていることについて追っていこうと思います。

アドレスバーにURLを指定されたWebブラウザの動作

1. http://www.example.comをアドレスバーに入力。

まずはブラウザのアドレスバーにURLを入力します。

68747470733a2f2f6573612d736d61727468722e73332d61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f75706c6f6164732f70726f64756374696f6e2f6174746163686d656e74732f31313434392f323031392f31312f33302f36333932342f66356636363631342d363337362d.png

2. www.example.comのIPアドレスを探す(DNS解決)

www.example.comサーバーにあるリソース(HTML)を取得したいというリクエストを送りたいのですが、www.example.comのままではブラウザはwww.example.comのサーバーの場所は分かりません。

www.example.comのサーバーの場所を探すためにルートサーバーにwww.example.comのIPアドレスを問い合わせます。

68747470733a2f2f6573612d736d61727468722e73332d61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f75706c6f6164732f70726f64756374696f6e2f6174746163686d656e74732f31313434392f323031392f31312f33302f36333932342f62646630653338342d386432612d.png

3. www.example.comのIPアドレスに対してTCPの80番ポートで接続する

www.example.comのIPアドレスが分かったので、さっそくサーバーにリクエストを送りたいのですが、Webを含む、インターネットにおける通信の大半がTCPを前提にしています。

TCPで通信を行うためにはまず接続するという作業が必要です。

  1. 通信を開始したい側が「このポート番号で接続させてください」という接続要求パケットを送信する
  2. その接続を受け入れるのであれば「いいですよ」という応答を返す
  3. 受け取った通信を開始したい側は「ありがとうございます。お願いします!」という内容を送信してTCP接続が確立。

(↑は3回メッセージがやり取りされるので、3 way handshake と呼ばれています。)

68747470733a2f2f6573612d736d61727468722e73332d61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f75706c6f6164732f70726f64756374696f6e2f6174746163686d656e74732f31313434392f323031392f31312f33302f36333932342f31373434303332632d316630372d.png

4. リクエストメッセージを送信する

TCP接続が成功したので、やっとwww.example.comにリクエストを送れます。

WebブラウザとWebサーバーの間ではHTTPでやり取りをしているので、HTTPリクエストメッセージを送信します。

image (5).png

(HTTPリクエストメッセージはChrome DevToolsのNetworkパネルから確認することができます。)
image (6).png

5. サーバーがメッセージを受け取り、レスポンスメッセージを返信する。

WebブラウザからのHTTPリクエストを受け取ったWebサーバーは、要求されたリソースをWebブラウザに返します。

image.png

6. リソースの読み込み(loading)

リソースを受け取ったWebブラウザですが、受けとったリソースのHTMLをそのまま表示させる訳にはいきません。

解釈した上で画面に表示しなければなりません。

リソースのDownload

HTMLをサーバーから受け取りましたが、どうやらHTMLには画像やCSS参照されている記述があります。

ブラウザは受け取ったHTMLにCSS,JavaScriptや画像といったリソースの参照があれば、さらにそのリソースを読み込みます。

リソースの解釈 (Parse)

index.html
<html>
<head></head>
<body>
  <h1>My Header</h1>
  <a href="www.example.com">My link</a>
</body>
</html>

この状態ブラウザに表示させても全く分からないので、ブラウザがRenderingしやすいように読み込んだHTMLを解釈してドキュメントのDOMツリーを構築していきます。

image.png

同じようにCSSも解釈され、CSSOMツリーを構築していきます。
image (7).png

8. JavaScriptの実行 (Scripting)

リソースを一式読み込んだ後はJavaScript実行(Scripting)します。

レンダリングエンジンは、JavaScriptのコードを実行することができないのでJavaScriptエンジンに引き渡して実行させます。

ですが、このままのコードでは、JavaScriptエンジンは、実行することができません。
実行可能な形式に変換(コンパイル)しないと処理を実行することができないのです。

コンパイルを行うために、JavaScriptのコードを抽象構文木(AST:abstract syntax tree)と呼ばれるコンパイル可能な形に変換します。

  1. 字句解析を行い、トークン列に。
    image (1).png

  2. トークン列をもとに構文解析を行い抽象構文木(AST)に。
    image.png

  3. 抽象構文木を実行可能な形式にコンパイル

  4. 実行

9. レイアウトツリー構築 (Rendering)

JavaScriptの実行が終わるといよいよ画面に表示する準備に取り掛かります。

DOM と CSSOM を組み合わせて、ページ上の表示可能なすべての DOM コンテンツと、各ノードのすべての CSSOM スタイル情報を取り込んだレイアウトツリーを作成していきます。

image (2).png
image (3).png

レイアウト

レンダリング ツリーが出来たので、いよいよ画面に表示したいところですが、端末のビューポート内での要素の正確な位置とサイズはまだ分かりません。

ページ上の各オブジェクトの正確なサイズと位置を算定するために、

  • 要素の大きさ
  • 要素のmargin
  • 要素のpadding
  • 要素の位置

等のレイアウト情報の計算を行います。

image (4).png

10. レンダリング結果の描画(Painting)

レイアウト情報の算出の算出が終わったので、いよいよ画面に描画です。

レイアウトツリーが画面上のピクセルに変換されます。

これでやっと画面上にページが表示されました!

まとめ

アドレスバーにURLを入力してから、表示されるまでたくさんの処理があります。

こんなにたくさんの処理があるのに一瞬でページを表示してくれるブラウザって素敵だと思いませんか?

Webを見ているときに起きていることを理解してみると、普段何気なく書いてるJavaScriptのコードだったり、HTMLやcssの理解が深まる気がしています。

ブラウザの仕組みについて考えてみることで、フロントエンド開発で本当に大切なことが見えてくるような気がして、私はブラウザについて考えるのが好きです。


参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

リーダーブルコードを未経験が読んで理解したこと

触ってない言語、機能について書かれている今必要なさそうなところは飛ばして、自分(初心者)がすぐに実践できそうな知識についてまとめてみました。

優れたコードとは??

他者が読んで理解できるコード。
コードは短い方がいいが、『理解するまでの時間』を短くする方がよい。
そのため短くすることで逆にわかりにくくなるようであれば短くする必要はない。

名前に情報を詰め込む

変数や関数、クラス名でも名前に情報を詰め込むのが大事。名前は短いコメントのようなもの。
  • 明確な単語を選ぶ
    getPageだと何のページをgetしているかわからない。インターネットから取ってきたページなら、downLoadPage等の方がわかりやすい。

  • tmpやretvalなどの汎用的な名前は避ける。
    明確な理由があれば使用してもいい。

  • 抽象的な名前より具体的な名前を使う

  • 変数名に大切な情報を追加する
    ミリ秒を表す変数なら、変数名の後ろに_msとつけると何の変数かわかりやすい。

  • 名前の長さを決める

  • スコープが小さければ短い名前でも良い。

  • 頭文字と略語
    string⇨strなど他人にも通じる略語を使うのがいい。BackEndManager⇨BEM等、他の人がわからない略語はNG

  • 不要な単語は捨てる
    DoServeLoop()だったら、ServeLoop()でも必要な情報は損なわれてないのでOK。なくても通じる単語は捨てる。

  • 名前のフォーマットで情報を伝える
    エンティティごとに異なるフォーマットを使う。
    C++言語であれば、クラス名はキャメルケース、変数名は小文字にしてスネークケースで定義する、など。
    ローカル変数とクラス変数も、異なるフォーマットで書くと一目見て何かわかるので良い。

  • その他フォーマット規約
    プロジェクトや言語によってもフォーマット規約は変わってくる。
    JavaScriptでは、jQueryのライブラリ関数を呼び出したときは、変数名の頭に$をつけるというものがある。⇨iQueryのオブジェクトだと明確にわかるため。
    HTMLだと、タグのid名の区切り文字にはアンダースコアを、class名の区切り文字にはハイフンを使う規約が有力。

誤解されない名前をつける

自分のコードを読んでいる人が、自分の意図を正しく理解できることが大事。
  • 限界値を含め場合はminとmaxを使う。
    CART_TOO_BIG_LIMITという名前だと意味があいまい。(未満なのか以下なのかがわからない)⇨MAX_ITEM_IN_CARTのほうが意味が伝わりやすい。

  • 範囲を指定する場合はfirstとlastを使う
    startは適切な名前になるが、stopは複数の意味に解釈できるため、firstとlastを使用する方が適切。

  • 包含/排他的範囲にはbeginとendを使う

  • ブール値(真偽値)の名前
    read_passward = true
    パスワードをこれから読み取る?もう読み終わっている?適切な名前ではない。
    user_is_authenticated = true
    こっちのほうが適切。また、名前を否定形ではなく肯定系にしたほうがよい。

  • ユーザーの期待に合わせる
    getで始まるメソッドだとメンバの値を返すだけの軽量アクセであるという規約がある。
    この規約を守らないと、DBからすべてのレコードを取ってくるときの変数名にgetをつけたりすると、間違って使用したりしてコストが高くなってしまう。

  • 複数の名前を検討する

コードの美しさ

  • 一貫性のある簡潔な改行位置

  • メソッドを使った整列

  • 縦の線をまっすぐにする

$aaa     =  "test";
$b       =  "test";
$cccccc  =  "test";

イコールの位置を合わせると見やすい。

  • 一貫性と意味のある並び
    アルファベット順にしたり、「最重要」なものから重要度順に並べたり、対応する HTML フォームの フィールドと同じ並び順にするなど。

  • 宣言をブロックにまとめる

  • コードを段落に分割する
    文章と一緒。見やすくなる。

- 個人的な好みと一貫性
クラス定義のカギカッコの位置など、最終的には個人の好みによる部分が大きい。
間違ったスタイルを使っているプロジェクトもあるが、その場合はプロジェクトの規約に従うのが大事。
一貫性の方が重視される。

コメントすべきことを知る

  • コメントすべきではないことを知る
    コードを見てわかることは書かない。関数の名前と同じことを日本語でコメントアウトするなど

  • ひどい名前はコメントをつけずに名前を変える
    コメントで説明するくらいなら、関数等の名前をもっとわかりやすい名前に変える。
    関数名等はいろんなところで使用されるため、そっちを変えた方がよい。
    「優れたコード > ひどいコード + 優れたコメント」

  • 自分の考えを記録する
    優れたコメントというのは「考えを記録する」ためのものである。
    たとえばこんなの

// このデータだとハッシュテーブルよりもバイナリツリーのほうが 40% 速かった。
// 左右の比較よりもハッシュの計算コストのほうが高いようだ。

コメントから情報を得ることができ、下手に最適化しようとして時間を無駄に使う必要がなくなる。
コードが汚い理由を書いてもいい。

  • コードの欠陥にコメントをつける プログラマがよく使う記法
記法      意味        
TODO: あとで手をつける    
FIXME: 既知の不具合があるコード
HACK: あまりキレイじゃない解決策
XXX: 危険! 大きな問題がある
  • 定数にコメントをつける
    定数を定義するときはなぜその値を持っているかという背景を持っている

  • 読み手の立場になって考える

- 「全体像」のコメント

# 顧客が自分で購入した商品を検索する

このような、全体像が掴めるコメントをしておく。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

リーダブルコードを未経験が読んで理解したこと

触ってない言語、機能について書かれている今必要なさそうなところは飛ばして、自分(初心者)がすぐに実践できそうな知識についてまとめてみました。

優れたコードとは??

他者が読んで理解できるコード。
コードは短い方がいいが、『理解するまでの時間』を短くする方がよい。
そのため短くすることで逆にわかりにくくなるようであれば短くする必要はない。

名前に情報を詰め込む

変数や関数、クラス名でも名前に情報を詰め込むのが大事。名前は短いコメントのようなもの。
  • 明確な単語を選ぶ
    getPageだと何のページをgetしているかわからない。インターネットから取ってきたページなら、downLoadPage等の方がわかりやすい。

  • tmpやretvalなどの汎用的な名前は避ける。
    明確な理由があれば使用してもいい。

  • 抽象的な名前より具体的な名前を使う

  • 変数名に大切な情報を追加する
    ミリ秒を表す変数なら、変数名の後ろに_msとつけると何の変数かわかりやすい。

  • 名前の長さを決める

  • スコープが小さければ短い名前でも良い。

  • 頭文字と略語
    string⇨strなど他人にも通じる略語を使うのがいい。BackEndManager⇨BEM等、他の人がわからない略語はNG

  • 不要な単語は捨てる
    DoServeLoop()だったら、ServeLoop()でも必要な情報は損なわれてないのでOK。なくても通じる単語は捨てる。

  • 名前のフォーマットで情報を伝える
    エンティティごとに異なるフォーマットを使う。
    C++言語であれば、クラス名はキャメルケース、変数名は小文字にしてスネークケースで定義する、など。
    ローカル変数とクラス変数も、異なるフォーマットで書くと一目見て何かわかるので良い。

  • その他フォーマット規約
    プロジェクトや言語によってもフォーマット規約は変わってくる。
    JavaScriptでは、jQueryのライブラリ関数を呼び出したときは、変数名の頭に$をつけるというものがある。⇨iQueryのオブジェクトだと明確にわかるため。
    HTMLだと、タグのid名の区切り文字にはアンダースコアを、class名の区切り文字にはハイフンを使う規約が有力。

誤解されない名前をつける

自分のコードを読んでいる人が、自分の意図を正しく理解できることが大事。
  • 限界値を含め場合はminとmaxを使う。
    CART_TOO_BIG_LIMITという名前だと意味があいまい。(未満なのか以下なのかがわからない)⇨MAX_ITEM_IN_CARTのほうが意味が伝わりやすい。

  • 範囲を指定する場合はfirstとlastを使う
    startは適切な名前になるが、stopは複数の意味に解釈できるため、firstとlastを使用する方が適切。

  • 包含/排他的範囲にはbeginとendを使う

  • ブール値(真偽値)の名前
    read_passward = true
    パスワードをこれから読み取る?もう読み終わっている?適切な名前ではない。
    user_is_authenticated = true
    こっちのほうが適切。また、名前を否定形ではなく肯定系にしたほうがよい。

  • ユーザーの期待に合わせる
    getで始まるメソッドだとメンバの値を返すだけの軽量アクセであるという規約がある。
    この規約を守らないと、DBからすべてのレコードを取ってくるときの変数名にgetをつけたりすると、間違って使用したりしてコストが高くなってしまう。

  • 複数の名前を検討する

コードの美しさ

  • 一貫性のある簡潔な改行位置

  • メソッドを使った整列

  • 縦の線をまっすぐにする

$aaa     =  "test";
$b       =  "test";
$cccccc  =  "test";

イコールの位置を合わせると見やすい。

  • 一貫性と意味のある並び
    アルファベット順にしたり、「最重要」なものから重要度順に並べたり、対応する HTML フォームの フィールドと同じ並び順にするなど。

  • 宣言をブロックにまとめる

  • コードを段落に分割する
    文章と一緒。見やすくなる。

- 個人的な好みと一貫性
クラス定義のカギカッコの位置など、最終的には個人の好みによる部分が大きい。
間違ったスタイルを使っているプロジェクトもあるが、その場合はプロジェクトの規約に従うのが大事。
一貫性の方が重視される。

コメントすべきことを知る

  • コメントすべきではないことを知る
    コードを見てわかることは書かない。関数の名前と同じことを日本語でコメントアウトするなど

  • ひどい名前はコメントをつけずに名前を変える
    コメントで説明するくらいなら、関数等の名前をもっとわかりやすい名前に変える。
    関数名等はいろんなところで使用されるため、そっちを変えた方がよい。
    「優れたコード > ひどいコード + 優れたコメント」

  • 自分の考えを記録する
    優れたコメントというのは「考えを記録する」ためのものである。
    たとえばこんなの

// このデータだとハッシュテーブルよりもバイナリツリーのほうが 40% 速かった。
// 左右の比較よりもハッシュの計算コストのほうが高いようだ。

コメントから情報を得ることができ、下手に最適化しようとして時間を無駄に使う必要がなくなる。
コードが汚い理由を書いてもいい。

  • コードの欠陥にコメントをつける プログラマがよく使う記法
記法      意味        
TODO: あとで手をつける    
FIXME: 既知の不具合があるコード
HACK: あまりキレイじゃない解決策
XXX: 危険! 大きな問題がある
  • 定数にコメントをつける
    定数を定義するときはなぜその値を持っているかという背景を持っている

  • 読み手の立場になって考える

- 「全体像」のコメント

# 顧客が自分で購入した商品を検索する

このような、全体像が掴めるコメントをしておく。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【CSS】要素の縦中央揃えをいい加減攻略したい。

はじめに

この記事は 株式会社ピーアールオー(あったらいいな!を作ります) Advent Calendar 2019 の5日目の記事です。
突然の初学者向けみたいな内容ですが、よろしくお願いします。

今年は一年かけて、Angularを用いたWebサイトの開発に邁進していました。
Angular、モジュールを分割することで中々気持ちよく開発できるフレームワークだったのですが、モジュール分割をしてる都合上どうしてもCSSを弄らなければならないシーンが多く、弱点:CSSな自分は結構躓いてしまうシーンが多かったです。
中でも毎回悩ませてくれたのが、タイトルにもなっている縦中央揃えです。

縦中央揃えとは

名前の通り、要素を縦中央に沿って並べることです。
Angularなどのフレームワークではモジュールが独立しているため、要素のサイズを事前に決定することができない事が多いため、意外と多用することになります。

理想としてはこんな感じ。
image.png

ただ、どうにもこの縦中央揃え、世に書かれているおすすめコードを試してみても効いたり効かなかったりして、最終的に
「色々試してたら書き散らかしたコードが上手い具合に効いて縦中央に揃ったわ!ヨシ!」
となりがちだったので、今回はこの場を借りて巷でよく聞く縦中央揃えの手法を実際にいじり倒してみようかと思います。

確認環境

  • Google Chrome 78.0.3904.108
  • Firefox 70.0.1
  • Microsoft Edge 44.18362.449.0
  • Internet Explorer 11.476.18362.0

(スクリーンショットはGoogle Chromeを使用)

ベースコード

ちょっと長いので折り畳み
sample.html
<head>
  <style>
    .parent-box {
      display: block;
      width: 350px;
      height: 200px;
      border: 3px solid rgba(100, 0, 0, 1);
      background: linear-gradient(
        180deg,
        #ff9999 0%,
        #ff9999 50%,
        #ffff99 50%,
        #ffff99 100%
      );
    }

    .child-box {
      display: inline-block;
      width: 100px;
      border: 3px solid rgba(0, 0, 100, 1);
      background-color: rgba(100, 100, 255, 0.3);
    }
    .child-box.one {
      font-size: 16px;
      height: 50px;
    }
    .child-box.two {
      font-size: 24px;
      height: 80px;
    }
    .child-box.three {
      font-size: 12px;
      height: 30px;
    }
  </style>
</head>
<body>
  <div class="parent-box">
    <span class="child-box one">Child1</span>
    <span class="child-box two">Child2</span>
    <span class="child-box three">Child3</span>
  </div>
</body>

事前知識:inline要素の縦位置の相互作用

縦中央揃えに行く前に、まずinline要素を並べたときにどんな相互作用が発生するか理解しておく必要があります。

では、まずなんも考えずにベースコードを実行して、何が表示されるか見てみましょう。
no-style.png
…一番上にきちっと揃うのを期待してましたがガッタガタですね。個人的にもうこの時点でなんでやねん!とベタな突っ込みをしてしまいそうになるのですが、一旦落ち着いて1本補助線を引いてみましょう。
baseline.png

フォントサイズの違う3つの文字がきっちりラインで揃ってるのがわかると思います。
このラインがbaselineです。vertical-alignによって位置設定がされていないinline要素は、「alphabetic」というアルファベットベースのbaselineによって、位置が規定されます

もう少しbaselineがどういう動きをするか、色々試してみましょう。
例えば、画像・二行以上の文章・要素の中身なしだと…?
iroiro.png
どうやら、画像の下・一番下の行の下・要素自体の一番下がbaselineとして設定されるようです。
直感的といえば直感的な揃い方ですかね…?

inline要素はこのように同じラインにある子要素の影響を受ける可能性のある要素ということを覚えておく必要があります。

さて、この知識を武器に縦中央揃えを攻略していきましょう。

よく聞く縦中央揃えの手法

今回は以下の5つの縦中央揃えの手法を試してみたいと思います。

  • vertical-align: middle;
  • line-height: (親要素の高さ);
  • margin: auto 0;
  • transform
  • display: table-cell;

vertical-align: middle;

名前が縦中央に揃えられるぜ感を出してるせいで、最初に適当に試して玉砕しがちな手法ですね。

まず、vertical-alignは子要素同士の位置関係性を定義するプロパティです。
したがって、子要素に対して付与するプロパティとなります。

では試しに子要素につけてみましょう。
middle1.png
お、未適用の状態に比べるとbaselineの制約が消えて縦中央に揃いましたね。いやーめでたsコレジャナイ。
はい。やりたいのは親要素に対する中央揃えなので、子要素の縦中央だけ合わせても仕方ないですね。
子要素の中央揃えも必要になりますので、vertical-align: middle; は他の中央揃えの手法と組み合わせて使うのが基本のようです。

ただし、どれかの子要素の縦の中心が親要素の中心と一致している場合 (例:親要素の高さ=子要素の高さ)、vertical-alignのみでも他の要素の縦中央揃えが可能です。
試しにChild3の縦中心を親に合わせてみたのが以下です。
image.png
Child3のボックスに引きずられて、Child1,2どちらも縦中央に揃っています。
このやり方は一つでも高さを指定できるinline-blockが入っていれば有効ですので、意外とこれだけでなんとかなるシーンは多そうです。

line-height: (親要素の高さ);

テキストがline-heightに対して縦中央に配置されることを利用して、無理やり縦中央揃えに利用してしまおうという、どこなくパワーを感じる手法ですね。

まあ、まずは何も考えずに適用してみましょう。テキストに対するプロパティなので適用は「親要素」「子要素全て」のどちらでもOKです。
image.png
あっ、はい。
inline-blockだと内部テキストにデザインが追従しないので文字だけが吹っ飛んでしまうようですね…。また、Child2のbaselineに引きずられて、Child1, Child3の文字が中央からずれているようです。

では、子要素のdisplay: inline-block;display: inline;に変更して、子要素同士が縦中央に並ぶようにvertical-align: middle;を追加してみましょう。
image.png
縦中央に並びましたね!
元のinline-blockを利用する想定とは違いますが、inlineの子要素のみならこれでも行けそうです。
ただし、line-heightは値として"100%"が使用できないので親要素の高さが固定であることが前提となるのに注意する必要があります。

margin: auto 0;

自動的に揃えたい時にautoって単語は非常に心地よく耳に響きますよね。
flexboxのmarginの上下にautoを設定するとうまい具合に(よくわかってないの意)中央揃えになってくれる機能を利用したものです。

もう説明からして求めているものですが、落ち着いて適用してみましょう。
親要素に、display: flex;、子要素にmargin: auto 0を適用しています。
image.png
かなりきれいな中央揃えになりました!baselineの影響も受けていないようです。

なにかすんなり行き過ぎて悔しいので、子要素がinline要素の場合も試してみましょうか。
全ての要素をinlineにして確認してみます。
image.png
悔しいことにこちらもきれいに縦中央揃えになるようです。

Flexboxを利用して問題のないデザインであれば縦中央揃えはmargin: auto 0;が安定しているようです。

transform

失敗が続きパラメータによる自動整列が信用できなくなってくる頃に使いたくなってくる、ちゃんと要素をずらして縦中央揃えを実現する手法です。
以下の三つの要素を子要素に適用することで縦中央揃えを実現します。

{
      position: relative;
      top: 50%;
      transform: translateY(-50%);
}

上記CSSの挙動としては、
1. 親要素の高さの50%の位置を始点に子要素を描画する(top: 50%;)
2. 子要素の高さの50%だけ子要素を上に移動させる(transform: tranlateY(-50%);)
といった感じです
50%の意味が異なるのでちょっと混乱しますが、動作を書きだしてみるとシンプルで間違いのない縦中央揃え方法ですね。

では、子要素に適用してみましょう。
image.png
んん? なぜかChild1, Child3が微妙に中央からずれてしまっていますね…。baselineに沿っているような感じでもないですし…。
確認のために、transform: tranlateY(-50%); を外してみましょうか。
image.png
なるほど、どうやらこれもbaselineの影響のようです。transform: tranlateY(-50%); で綺麗に中央に寄るには全子要素の一番上が親要素の中央線と同じ場所になければなりません。
それが達成できるように、子要素を上揃えにするvertical-align: top;を追加して改めてやりなおしてみます。
image.png
よし!きれいに縦中央揃えになりました!。

では、inline要素の場合はどうでしょうか?全ての要素をinlineにしてみます。
image.png
うーん、どうやらtransform: translateY(-50%);が機能していないようです。inline要素は高さを持っていませんので、その影響だと思われます。

今回の様にinline-blockで構成されている子要素ならば問題ないですが、inline要素の場合は別の縦中央揃えを利用するほうが良さそうです。

display: table-cell;

縦中央揃えって言葉から中々連想が出来ない秘策がdisplay: table-cell;です。
基本的な使い方は、親に以下の要素を追加する形です。

{
    display: table-cell;
    vertical-align: middle;
}

では試しにやってみましょう。
image.png
あ、なんかもう見慣れた感じのズレですね。余計な事は言わず粛々と子要素にvertical-align: middle;を追加しましょう。
image.png
綺麗に縦中央揃えになりました!
このまま子要素をinlineにしてみましょう。
image.png
inlineにしても問題なく縦中央揃えになるようです!

かなりお手軽に中央揃えが出来るtable-cellですが、ちょっと特殊な要素でもありますので使う際は意識しておく必要がありそうです。
※ 以下の記事がtable-cellの制約について詳しく解説しています。
display:table-cell;を安易に使うべきでない理由いろいろ

まとめ

各縦中央揃えについて

vertical-align: middle

  • 通常は親要素に対して縦中央揃えはできない。
    • 親要素と縦の中心が一致している子要素があれば可能。
ベースコードへの適用例

コード
sample-vertical.html
<head>
  <style>
    .parent-box {
      display: block;
      width: 350px;
      height: 200px;
      border: 3px solid rgba(100, 0, 0, 1);
      background: linear-gradient(
        180deg,
        #ff9999 0%,
        #ff9999 50%,
        #ffff99 50%,
        #ffff99 100%
      );
    }

    .child-box {
      display: inline-block;
      width: 100px;
      border: 3px solid rgba(0, 0, 100, 1);
      background-color: rgba(100, 100, 255, 0.3);
      vertical-align: middle;
    }
    .child-box.one {
      font-size: 16px;
      height: 50px;
    }
    .child-box.two {
      font-size: 24px;
      height: 80px;
    }
    .child-box.three {
      font-size: 12px;
      height: 194px;
    }
  </style>
</head>
<body>
  <div class="parent-box">
    <span class="child-box one">Child1</span>
    <span class="child-box two">Child2</span>
    <span class="child-box three">Child3</span>
  </div>
</body>

line-height: (親要素の高さ)

  • 縦中央揃えが適用されるのはinline要素のみ。
  • 親要素の高さが固定長である必要がある
  • 各要素のbaselineが異なる場合、vertical-align: middleを適用する必要あり。
ベースコードへの適用例

コード
sample-line.html
<head>
  <style>
    .parent-box {
      display: block;
      width: 350px;
      height: 200px;
      border: 3px solid rgba(100, 0, 0, 1);
      background: linear-gradient(
        180deg,
        #ff9999 0%,
        #ff9999 50%,
        #ffff99 50%,
        #ffff99 100%
      );
      /* ボーダーの影響を受けるため、3px * 2だけ小さくする必要がある */
      line-height: 194px;
    }

    .child-box {
      display: inline;
      border: 3px solid rgba(0, 0, 100, 1);
      background-color: rgba(100, 100, 255, 0.3);
    }
    .child-box.one {
      font-size: 16px;
    }
    .child-box.two {
      font-size: 24px;
    }
    .child-box.three {
      font-size: 12px;
    }
  </style>
</head>
<body>
  <div class="parent-box">
    <span class="child-box one">Child1</span>
    <span class="child-box two">Child2</span>
    <span class="child-box three">Child3</span>
  </div>
</body>

margin: auto 0;

  • inline要素、inline-box要素どちらでも正しく縦中央揃えを実行することができる
  • 親要素をflexにする必要があるため、適用できるかは要検討。
ベースコードへの適用例

コード
sample-margin.html
<head>
  <style>
    .parent-box {
      display: flex;
      width: 350px;
      height: 200px;
      border: 3px solid rgba(100, 0, 0, 1);
      background: linear-gradient(
        180deg,
        #ff9999 0%,
        #ff9999 50%,
        #ffff99 50%,
        #ffff99 100%
      );
    }

    .child-box {
      display: inline-block;
      width: 100px;
      border: 3px solid rgba(0, 0, 100, 1);
      background-color: rgba(100, 100, 255, 0.3);
      margin: auto 0;
    }
    .child-box.one {
      font-size: 16px;
      height: 50px;
    }
    .child-box.two {
      font-size: 24px;
      height: 80px;
    }
    .child-box.three {
      font-size: 12px;
      height: 30px;
    }
  </style>
</head>
<body>
  <div class="parent-box">
    <span class="child-box one">Child1</span>
    <span class="child-box two">Child2</span>
    <span class="child-box three">Child3</span>
  </div>
</body>

transform

  • inline-block要素は縦中央揃えにすることが可能
    • 各要素のbaselineが異なる場合、vertical-align: top; で調整する必要がある。
  • inline要素はうまく縦中央揃えにすることができない。
ベースコードへの適用例

コード
sample-transform.html
<head>
  <style>
    .parent-box {
      display: block;
      width: 350px;
      height: 200px;
      border: 3px solid rgba(100, 0, 0, 1);
      background: linear-gradient(
        180deg,
        #ff9999 0%,
        #ff9999 50%,
        #ffff99 50%,
        #ffff99 100%
      );
    }

    .child-box {
      display: inline-block;
      width: 100px;
      border: 3px solid rgba(0, 0, 100, 1);
      background-color: rgba(100, 100, 255, 0.3);
      position: relative;
      top: 50%;
      transform: translateY(-50%);
      vertical-align: top;
    }
    .child-box.one {
      font-size: 16px;
      height: 50px;
    }
    .child-box.two {
      font-size: 24px;
      height: 80px;
    }
    .child-box.three {
      font-size: 12px;
      height: 30px;
    }
  </style>
</head>
<body>
  <div class="parent-box">
    <span class="child-box one">Child1</span>
    <span class="child-box two">Child2</span>
    <span class="child-box three">Child3</span>
  </div>
</body>

display: table-cell;

  • inline要素、inline-box要素どちらでも正しく縦中央揃えを実行することができる
  • 親要素をtable-cellにする必要があるため、適用できるかは要検討。
ベースコードへの適用例

コード
sample-table.html
<head>
  <style>
    .parent-box {
      display: block;
      width: 350px;
      height: 200px;
      border: 3px solid rgba(100, 0, 0, 1);
      background: linear-gradient(
        180deg,
        #ff9999 0%,
        #ff9999 50%,
        #ffff99 50%,
        #ffff99 100%
      );
    }

    .child-box {
      display: inline-block;
      width: 100px;
      border: 3px solid rgba(0, 0, 100, 1);
      background-color: rgba(100, 100, 255, 0.3);
      position: relative;
      top: 50%;
      transform: translateY(-50%);
      vertical-align: top;
    }
    .child-box.one {
      font-size: 16px;
      height: 50px;
    }
    .child-box.two {
      font-size: 24px;
      height: 80px;
    }
    .child-box.three {
      font-size: 12px;
      height: 30px;
    }
  </style>
</head>
<body>
  <div class="parent-box">
    <span class="child-box one">Child1</span>
    <span class="child-box two">Child2</span>
    <span class="child-box three">Child3</span>
  </div>
</body>

子要素の属性による縦中央揃えの効きの有無

手法 inline-block要素 inline要素  親要素制約
vertical-align: middle (高さ指定) △※ なし
line-height: (親要素の高さ) × 固定長が指定できること
margin: auto 0; 親表示要素がflexであること
transform × なし
display: table-cell; 親表示要素がtable-cellであること

※ 縦中央が親と一致するinline-blockが混在している場合は、縦中央揃えが可能。

感想

いじり倒してる内に万能の解法が見つからないかな、と淡い期待を持っていたのですが、やはり手法が乱立してるだけあって一長一短、中々簡単にはいかないようです…。
ただ、これなら効く、効かないというのが割とはっきりしたので、今後縦中央揃えにチャレンジしなければならなくなっても上手く立ち回れそうです。
あと、とりあえずCSSで記事書くのはめっちゃしんどい事はわかりました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む