20201223のCSSに関する記事は8件です。

【初心者でもわかる】CSSで立体文字を再現する方法

どうも7noteです。CSSで3Dの文字を再現するには。

基本的にwebサイトは平面ですが、立体感のある表現をしたい時にちょっと無理やりですが文字を立体にさせることができます。

見本
sample.png

立体文字の書き方

index.html
<div class="text">777</div>
style.css
.text {
  font-size: 30px;    /* 文字サイズを30pxにする */
  font-weight: bold;  /* 太文字にする */
  text-shadow: 1px 1px 0 #666,2px 2px 0 #666,3px 3px 0 #666;  /* 影を3重に指定 */
}

正確には立体ではなく、あくまでも立体に見せかけているだけですが、パッと見はそれほど気にならないと思います。
影を3重にして、左上に伸びているような立体感を再現しています。

背景色を使うとこんなかんじの立体感も再現することができます。

sample2.png

style.css
.text {
  color: #99f;
  font-size: 30px;
  font-weight: bold;
  text-shadow: 1px 1px 0 #fff,2px 2px 0 #fff,-1px -1px 0 #fff;
  background: #99f;
  padding: 5px;
}

まとめ

グラデーションをつけたり、さらに立体化を求めるなら画像にするしか今は方法がないかもしれませんね。

おそまつ!

~ Qiitaで毎日投稿中!! ~
【初心者向け】WEB制作のちょいテク詰め合わせ

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

cssでスクロールされすぎないようにする

Webサイトによっては画面トップでタッチパッドを2本指で上から下にタップすると白い領域が表示されちゃいます。

over scrollingって言うみたいですが最近になってやっと修正方法がわかりました。
フロントやってる人からすれば常識なんでしょうけれども、知らない悩んでしまうのでメモに残します。

対応策はcssをちょっと追加するだけ。

site.css
html {
  overflow: hidden;
  height: 100%;
}

body {
  overflow: auto;
  height: 100%;
}

以上です。簡単ですね。
私はググったとき目から鱗でした。

追記

なぜかこのcssいれるとpagespeed insightsのスコアが上昇しました。
理由が分からない・・・

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

:where()は詳細度戦争を終結させてくれるかもしれない

Firefox 78からCSSのwhereセレクタが正式実装された。
先進的な機能を搭載したMozillaに称賛を送りたい。FireFoxを使い続けてよかった…
少し遅れて、Safari 14でも使用可能とのこと。Macは持っていないので、iPhoneで確認しようっと。
Chromeでも、Experimental Web Platform featuresフラグをオンにすると体験できる。チェックしてみたところ、以下で紹介する例では大きな問題が発生していない。バージョン88で正式実装予定とのこと1
さて、今回の記事ではそのwhereセレクタが持つ真の意味を説明していきたい。
それは、今までWebデザイナーを苦しめてきたCSS仕様の呪縛からの解放である。

CSSの呪縛とは

すなわち「詳細度(Specificity)」だ。
CSSの黎明期から存在するこの規則は、むしろCSSの特徴であるカスケードを邪魔する機能があったのではないかと筆者は思う。

問題点:物理的な配置指定と詳細度の高さを単純に同一視している

例えば次のようなhtmlにCSSを追加する場合を考える。

company.html
<dl class="company_info">
  <dt>会社名</dt>
  <dd>株式会社ケイケイ(KK.inc)</dd>
  <dt>資本金</dt>
  <dd class="capital">8,000万円</dd>
</dl>
company.css
.company_info {
  display: grid;
  grid-template-columns: 5em auto;
}
.company_info dt {
  font-weight: bold;
  color: #400;
}
.company_info dt::after {
  content: ":"
}
.company_info dd {
  color: #b00;
  margin: 0;
}
.capital {
  color: gold;
  backgound: black;
}

いろいろ突っ込みどころがある2コードだが、説明のためだと思って笑って許していただきたい。

ここで問題。<dd class="capital">の文字色(color)は何色だろうか? CSSに日常的に触っている人なら即答できるはずだ。

答えは#b00、赤茶色である。詳細度は.company_info dd(0:1:1) > .capital(0:1:0)だからである。

そんなことは分かり切っている。ここで気になるのは、このコードを書いた人間はどのように考えてこんなコードにしたのだろうということだ。
おそらく彼(女)は詳細度を引き上げるつもりでこんな書き方をしたのではなかろう。companyというクラスのdlに含まれるddにはとりあえずcolorがついてほしいというだけのはずである。そして色を後から書き換えるユーティリティクラスとして.capitalを作った。だが残念なことに作成者はCSSの法則を理解していなかった。
https://codepen.io/NagayamaToshiaki/pen/wvGKJxy

この問題をどのように解決するか、実例を挙げていく。

解決策1:!important を使用する

例えば、cssを以下の様にすれば.capitalは作成者の意図通りの色になるはずである。

company.css
/* 前略 */
.company dd {
  color: #b00;
  margin: 0;
}
.capital {
  color: gold !important;
  backgound: black;
}

!importantは「それが宣言リストのどこであっても、この宣言は CSS 内で作られたその他の宣言を上書き」する(MDNより)。これはとりあえず問題を回避するには十分な解法である。.capitalがユーティリティクラスのため、これを上書きしたいという要求はまずないだろう。
しかし、!importantは諸刃の剣である。CSSの順序や詳細度を無視するため、「最強の矛と最強の盾」問題が発生する。要はプログラムの規模がでかくなると管理が行き届かなくなる。それに各属性にいちいち!importantを付けなければならないので、指定する必要がある属性が増えるほど付け忘れたりと、ケアレスミスの温床になる。

解決策2:.capitalの詳細度を上げる

例えばdd.capitalとすれば、.company_info ddと詳細度が等しくなり、ソースコードの順番からdd.capitalのほうが勝つ。ほかにはコンテナ(親要素)の要素名やクラス名を記載する方法もある。なお、.capital.capitalと繰り返しても詳細度を引き上げられるが、!importantと同じような問題がある。
しかし、このようなやり方を続けると本来.capitalに持たせたかった汎用性が失われ、html上で必要な分だけ.capitalを用意しなければならなくなる。最初の例ならdtも金色にしたいときはdt.capitalセレクタを記述しないといけない。そして何よりも、詳細度の引き上げであっちも上げなくちゃ、こっちも上げなくちゃという事態が発生する。言わば詳細度戦争である。

解決策3:すべてのスタイルをクラス指定のみにする

この方式を取り入れた一番有名な例が妖怪人間BEMである。要するに以下の様なコードにしてしまうのだ。

company_bem.html
<dl class="company_info">
  <dt class="company_info__dt">会社名</dt>
  <dd class="company_info__dd">株式会社ケイケイ(KK.inc)</dd>
  <dt class="company_info__dt">資本金</dt>
  <dd class="company_info__dd company_info__dd--capital">8,000万円</dd>
</dl>
company_bem.css
.company_info {
  display: grid;
  grid-template-columns: 5em auto;
}
.company_info__dt {
  font-weight: bold;
  color: #400;
}
.company_info__dt::after {
  content: ":"
}
.company_info__dd {
  color: #b00;
  margin: 0;
}
.company_info__dd--capital {
  color: gold;
  backgound: black;
}

これだったら詳細度が固定され、cssの管理が飛躍的にしやすくなる。
しかし、CSS本来の特性であるカスケードが有効活用できないのは残念だし、htmlコードのほうが長くなる。また、個人的にはclass属性の但し書き「コンテンツの期待するプレゼンテーションを記述する値よりもむしろ、コンテンツの性質を記述する値を使用するよう推奨される」(HTML Standard 日本語訳より)が無視されてしまうことが気になる3

解決策4:ユーティリティークラスを多用する

要するにBootstrapのような見た目の指定に特化したテンプレートを利用してしまおうという話。もしくは関数型CSS (atomic CSS, functional CSS)と言って、CSSを値指定に特化してしまおうという考え方もある。自分はBootStrapに関する知識がそれほどないので、自前でそれっぽいユーティリティークラスを用意する。

company_bem.html
<dl class="grid-dl">
  <dt class="bold after-colon color-400">会社名</dt>
  <dd class="color-darkRed m0">株式会社ケイケイ(KK.inc)</dd>
  <dt class="bold after-colon color-400">資本金</dt>
  <dd class="color-gold back_in_black m0">8,000万円</dd>
</dl>
company_bem.css
.grid-dl {
  display: grid;
  grid-template-columns: 5em auto;
}
.bold {
  font-weight: bold;
}
.color-400 {
  color: #400;
}
.after-colon::after {
  content: ":"
}
.color-darkRed {
  color: #b00;
}
.m0 {
  margin: 0;
}
.color-gold {
  color: gold;
}
.back_in_black {
  backgound: black;
}

この方法の優れている点は、見た目だけに注力できるので、デザインの調整がしやすくなることである。デザイナーにとっては一番扱いやすいだろう。Bootstrapは感覚的に見た目の良いサイトを構築できるようにできているので、筆者のような美的音痴にはうってつけだ。

しかし、筆者はあまりこのような手段を使いたくない。このような使い方はソースのセマンティック性を損ねているからだ。簡単に言えば、目の見えない人に「ここは金色文字ですよ」と言っても意味が無い。また、外面ばかり気にしていると、HTMLの書き方が雑になり、divの乱用や間違ったタグの使い方という悲劇が起こる。そうなるとARIAなどを使わなければならなくなる。本来ARIAは付加的なものなので、HTMLが意味を持って書かれていれば必要性は少ないはずだ

しかも、この手のユーティリティーは特定の画面サイズ、例えば横幅1366pxなどに特化したものになりがちなので、画面サイズがそれよりも小さければ容易に崩れる(大きくても、見れはするがスペースの有効活用がされないことが多い)。関数型CSSは特にこれらの問題に直面しやすい(さすがに企業のサイトではメディアクエリなどで対策しているはずだが)。Bootstrapはそこら辺を考慮してはいるが、結局想定サイズを何種類も用意してあるだけなので、横幅毎に(可能な限り)最適な選択肢を設定しなければならないわけだ。

総じて、ユーティリティークラスは現代のテーブルレイアウトと言ってよいと思う。現在の問題を解決するにはかなり強力だが、その本質は間違った使い方に基づいているからだ。

解決策5::where()を使う

長々と今までの解決策を語ってたが、ようやく本題。今までcssの記述と詳細度が一体のものとして扱われてきたが、それを打ち崩すセレクタが2つ登場した。:where():is()だ。
両者ともカッコ内に含まれたcssセレクタのいずれかと対応する要素にcssを当てていくが、:is()カッコ内の一番詳細度が高いセレクタの詳細度を採用するのに対して、:where()詳細度を無視する。これらのおかげで、詳細度の管理が格段に楽になる。

特に:where()の登場は今までのCSSの常識を覆す、いわゆるゲームチェンジャーだ。だって、構造を指定するだけのセレクタは全部where()にぶっこんでしまえば詳細度管理の手間が省けるのだから

company_where.css
.company_info {
  display: grid;
  grid-template-columns: 5em auto;
}
:where(.company_info) dt {
  font-weight: bold;
  color: #400;
}
:where(.company_info) dt::after {
  content: ":"
}
:where(.company_info) dd {
  color: #b00;
  margin: 0;
}
.capital {
  color: gold;
  backgound: black;
}

これで.company_infoの詳細度に悩まされることが無くなる。常に一番右以外のセレクタは:where()で囲んでいいのではないだろうか。

https://codepen.io/NagayamaToshiaki/pen/ExKVWmz

終わりに

そもそも、CSS1が策定された当時、ここまで大規模なWeb開発は想定されていなかったのではないかと思う。だから、詳細度という実装が簡単そうなシンプルなルールを考えたのではというのが筆者の持論。多分、右側から詳細度を比較していくルール4だったら、BEMが登場する理由は無かった。それはそれで問題が発生していたかもしれないが、ペーペーの筆者には思い当たらない。

CSS制定段階の設計ミスを挽回できる機会がようやく整ったことを喜びたい。来年1月からほぼすべての現行ブラウザで使えるようになる:where()セレクタのおかげでCSSは書きやすく、管理しやすいものになっているだろう。来年はIEの放逐が進み、デザイナーの負荷軽減がなされることが予想されるが、CSSの進化の恩恵は特に大きい。


  1. この答えを引き出したのは筆者です(手前味噌)。なお、Chrome Platform Statusでは「Enabled by default」となっているが間違い。なぜ修正されないんだ… 

  2. なんでcolor指定がRGBとキーワード混在なのか、そもそもddに色を付けることがコードとして適切とは思えない。 

  3. まあ、ユーティリティクラスを使っている時点で、この但し書きを無視しているんだけれどもね。 

  4. 今回は.capitalddの比較をして、.capitalの方が大きいから優先される。もし等しい詳細度なら左側のセレクタを見て決めるというアルゴリズム。 

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

S3 で ホスティングしたウェブサイトをSSL化し、かつ特定の IP のみに開示する方法

はじめに

この記事は2020年の RevComm アドベントカレンダー25日目の記事です。クリスマス当日ですね!

前日は @qii-purine さんの「pythonでのアーキテクチャを考える」でした。

今回は最後となりますが、S3 で ホスティングしたウェブサイトをSSL化し、かつ特定の IP のみに開示する方法について紹介します。

やりたいこと

aws 使っている会社で、自分の作ったサイト(例えばデモサイト)を社内で共有するとき、みなさまどのように共有しますか。

典型的なやり方だと EC2 や Fargate でフロントエンドのサーバを立てるのではないかと思います。また、複数の静的ウェブページであれば、サーバーレスも検討するのではないかと思います。

そんな中、A) 頻繁にアクセスしない、B) 静的ファイルでも良い といった場合、 S3でのホスティング はコスト的に有効です。

しかし A) 社内のVPN のみで共有したい、B) サイトを転送時に暗号化したい と言う条件が加わると、SSL化特定のIPのみに開示 する必要があります。そのためには SSL 証明書発行 と ファイヤーウォール を用意する必要があります。

今回 Route 53, WAF, CloudFront, Certificate Manager, S3 を使って, どのようにSSL化して S3 でホスティングするかを紹介します。

また、今回 CloudFront を使いますが、CloudFront の場合はデータがキャッシュされるため、TTL (Time to Live) を意図的に設定しない限り変更が即時反映されません。TTL を短くすればいい話ですが、今回 S3 にあるサイトを変更したときにどのようにサイトを更新し、変更を即反映させるかについて紹介します。

( 内容はこちらのリンクとほぼ被りますので、もし、本記事でわからないことがあればそちらを読んでいただけると幸いです)

全体構成

全体構成はこんな感じです。

diagram.png

作成手順

取り組む前の準備

  • Route 53 でメインドメインをまだ作成していない場合は作成してください。
  • Route 53 に追加するレコード名を予め、検討してください。( revcomm-christmas-demo.example.com とします。)

素材の準備

まず、画像を用意します。(頑張ってコピー等でダウンロードしてください。)

christmas_tree.png

コードの準備

index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <title>Merry Christmas</title>
    <link rel='stylesheet' type='text/css' media='screen' href='main.css'>
</head>
<body>
    <div class="content">
        <img class="tree" src="./christmas_tree.png">
    </div>
</body>
</html>
main.css
.content{
    text-align:center;
    position: relative;
    width: 100%;
    height: 100%;
}

.content .text{
    position: absolute;
    text-align:center;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-family: 'Charm', cursive;
    font-size: 5em; 
}

html {
    width: 100%;
    height: 100%;
}

body{
    width: 100%;
    height: 100%;
    background: radial-gradient(#ffffff 50%, #91bee5 100%);
}


.ball{
    position: absolute;
    padding: 0px;
    margin: 0px;
    width: 20px;
    height: 20px;
    border-radius: 10px;
    background-color: rgb(218, 233, 247);
}

S3 の設定

S3 にアクセスし、バケットを新規作成してください。(revcomm-christmas-demo にします)

s00.png
s01.png

次にコンテンツをアップロードしてください。(ドラッグアンドドロップで可能)

s03.png

これで S3 にコンテンツが追加されました。

Certificate Manager の設定

SSL 証明書の作成です。
Certificate Manager にアクセスし、Region を N.Virginia にした状態で SSL 証明書の新規作成をクリックしてください。

image.png

予め検討した URL を入力してください。

image.png

DNS検証 にしてください。

image.png

レコード作成を選択してください。

image.png

レコードを追加すると、 Route 53 に SSL 証明書用のレコードが追加されます。

CloudFront の設定

CloudFront にアクセスし、CloudFront Distribution の新規作成をクリックしてください。

image.png

以下のようにパラメータを修正してください。(英語のままですが、ご容赦願います。)

  • Enable Origin Shield: No
  • Restrict Bucket Access: Yes
  • Origin Access Identity: Create New Identity
  • Generate Read Permissions on Bucket: Yes
  • Viewer Protocol Policy: Redirect
  • Price class: Use All Edge
  • Default Root Object: index.html
  • Alternate Domain Names: 予め検討した URL (revcomm-christmas-demo.example.com)
  • SSL Certificate: Custom SSL Certificate
  • Custom SSL: 予め検討した URL をタイプしてみてください。対応する SSL が出ます。(revcomm-christmas-demo と書けば出るはず)

cf01.png
cf02.png

しばらくすると、デプロイが完了します。(15分以上かかる可能性あり)
完了したら、 CloudFront のドメイン名をメモってください。

cf03.png

補足

  • S3 のポリシーも自動的に更新します。
  • OAI (Origin Access Identity) を使用することで、 S3 をpublic化をしない状態でホスティングすることができます。

Route 53 のレコード作成

Route 53 にアクセスし、ドメイン名 > レコードを追加 をクリックしてください。

image.png

レコードを作成してください。
Route ポリシーを Simple Route、 レコード名を予め検討した URL のサブドメイン名(revcomm-christmas-demo)、 レコードタイプをCNAME、 Value を先ほどメモった CloudFront を URL 入力してください。

image.png

WAF の設定

WAF にアクセスし、IP Sets で Region を Global (CloudFront) にした状態で新規 IP Set を作成してください。

image.png

IP を設定してください。

image.png

次にファイヤウィールの設定です。Web ACLs (Access Control List) で Region を Global (CloudFront) にした状態で 新規 ACL を作成してください。

image.png

任意の名前を設定して、関連リースの追加をクリックしてください。

image.png

WAF に関連するリソースを追加してください。(CloudFrontのID番号が表示する)

image.png

次へをクリックし、Add rules > Add my own rules ... をクリックしてください。

image.png

ルールタイプ IP Set を選択し、 ルール名(任意)を好きな名前にした状態で先ほど作成した IP set を入力し、作成してください。Default Action を Allow にしてください。

image.png

デフォルトを Block にしてください。

image.png

あとは ACL を作成して完成です。

結果

予め検討した URL (revcomm-christmas-demo.example.com) にアクセスすると、以下のようになります。

f00.png

ちなみに IP アドレスを変えると、以下のようになります。

f01.png

更新手順

次に更新方法です。

コードの修正

以下のようにコードを修正してください。

index.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset='utf-8'>
        <title>Merry Christmas</title>
        <link rel='stylesheet' type='text/css' media='screen' href='main.css'>
        <link rel="preconnect" href="https://fonts.gstatic.com">
        <link href="https://fonts.googleapis.com/css2?family=Charm:wght@700&family=Pacifico&display=swap" rel="stylesheet">
    </head>
    <body>
        <div class="content">
            <img class="tree" src="./christmas_tree.png">
            <div class="text">
                We wish you a Merry Christmas <br />
                and a Happy New Year
            </div>
        </div>
    </body>

    <script>
        function drop_snow(){

            var snow_ball = document.createElement("div")
            snow_ball.className = "ball"
            snow_ball.style.top = 0 + 'px'
            snow_ball.style.left = Math.random() * document.body.clientWidth  + 'px'

            var content = document.getElementsByClassName('content')[0]
            content.appendChild(snow_ball);

            var pos = 0
            var refreshIntervalId = setInterval(frame, 10);

            function frame() {
                if (pos > document.body.clientHeight) {
                    content.removeChild(snow_ball);
                    clearInterval(refreshIntervalId);
                } else {
                    pos+= 1;
                    snow_ball.style.top = pos + 'px';
                    snow_ball.style.opacity = (1 - pos/document.body.clientHeight)
                }
            }
        }

        for (let i=0; i < 10; i ++){
            drop_snow()
        }
        setInterval(drop_snow, 500);
    </script>

</html>
main.css
.content{
    text-align:center;
    position: relative;
    width: 100%;
    height: 100%;
}

.content .text{
    position: absolute;
    text-align:center;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-family: 'Charm', cursive;
    font-size: 5em; 
}

html {
    width: 100%;
    height: 100%;
}

body{
    width: 100%;
    height: 100%;
    background: radial-gradient(#ffffff 50%, #91bee5 100%);
}


.ball{
    position: absolute;
    padding: 0px;
    margin: 0px;
    width: 20px;
    height: 20px;
    border-radius: 10px;
    background-color: rgb(218, 233, 247);
}

S3に再度アップロード

再度作成した S3 バケットにアップロードしてください。

CloudFront のキャッシュ無効化

CloudFront を通して一度サイトにアクセスすると、作成したウェブページがキャッシュされます。
そこで、キャッシュを無効化する必要があります。キャッシュを無効化するためにはまず CloudFront にアクセスし、作成した CloudFront Distribution をクリックしてください。

cf10.png

Invalidations で 無効化の作成 をクリックしてください。

cf11.png

あとは index.html 入力し、無効化を実行してください。

結果、こんな感じになります。(codepen です。画像だとつまらないので。)

See the Pen aws_s3_ssl_example1 by zomaphone1 (@zomaphone) on CodePen.

まとめ

以上で、S3 で ホスティングしたウェブサイトをSSL化し、かつ特定の IP のみに開示する方法について一つ紹介しました。

通常のホスティングであれば S3 で設定が済みますが、SSL化 と 特定の IP に対して公開したい場合、上記の手段は有効です。

もちろん他の手段として、S3 だけで解決する手段もあります。

こちらの記事のようにアクセスポイントを変えるだけ https で公開することもできます。IP と https のみを許容する場合は bucket policy を変えるだけで済みます。

Before:
https://revcomm-christmas-demo.s3-website-ap-northeast-1.amazonaws.com/
After: 
https://s3-ap-northeast-1.amazonaws.com/revcomm-christmas-demo/index.html

ただし、このやり方で注意していただきたいのが、httpsindex.html を明示的に示さないといけないことです。そのため、共有するときに URL の扱いに注意しないといけなくなります。

もし、リダイレクト等も含めたい、index.html まで記述させたくない場合、ぜひこちらの記事を参考に実施していただけると幸いです。

最後に

いかがでしたでしょうか。

今回の Qiita advent calendar は RevComm として初の試みではありましたが、有益な情報は得られましたでしょうか。

RevComm では「コミュニケーションを再発明し、人が人を想う社会を創る」というミッションを基に、電話営業をディープラーニングの技術で支援するプロダクト( Miitel ) をはじめ、コミュニケーションに関わる様々なプロダクト開発を行っており、日頃からコミュニケーションの在り方を再定義するという難しい課題に取り組んでいます。

弊社ではテックに関わらず成長に貪欲な人がたくさんいます。会社としてまだまだ若いところもありますが、新しい技術等に積極的に取り入れる会社ではあるので、エンジニアとしてテックスタックを広げたいという人にとってはいい会社です。

もし、弊社で一緒に働きたいという想いがあれば、あるいは少しでも興味があればぜひぜひ弊社の採用ページに応募してみてください。

ちなみに働き方について興味があれば、ぜひ CTO が書いたこちらの記事を読んでください。

では良いクリスマスを!!

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

【CSS】いまさらだけどclearfixを知ったので図解します!

はじめに

今回はCSSでレイアウト崩れを防止できる、clearfixという手法をご紹介します!
この方法自体は2004年からあるらしく全然定番のお話らしいですが、自分は本を読んでて最近やっと仕組みがハラオチしたので、ぜひアウトプットさせていただきたく参上しました!

clearfixいつ使うの?:floatプロパティでレイアウト崩れちゃう!という場合

基本的にHTMLって縦方向に骨組みを作成するじゃないですか。

スクリーンショット 2020-12-05 21.23.48.png

これは夏目漱石のポートフォリオサイト「Kusa-Makura」(さっき作った)ですが、HTMLとしては以下のようになっています。(ボディー部のみ)

      <div class="main">
        <h1>About</h1>
        <section class="profile">
          <div class="profile-text">
            <h2 class="icon">Profile</h2>
            <p><span>夏目漱石</span><br>
              わし。なんかとてもすごい人。<br>
              すごすぎて顔が1000円札に使われていたこともある。<br>しかし今その辺でわしの1000円札を使おうとすると、店員にちょっと変な顔されると思うので注意されたい。<br>ここからWikipedia・・・本名は夏目 金之助(なつめ きんのすけ)。俳号は愚陀仏。明治末期から大正初期にかけて活躍した近代日本文学の頂点に立つ作家の一人である。代表作は『吾輩は猫である』『坊っちゃん』『三四郎』『それから』『こゝろ』『明暗』など。明治の文豪として日本の千円紙幣の肖像にもなり、講演録「私の個人主義」も知られている。漱石の私邸に門下生が集った会は木曜会と呼ばれた。・・・ここまでWikipedia</p>
          </div>
          <img src="images/natsume.jpg" alt="夏目漱石のプロフィール画像" class="profile-image" width="200">
        </section>
        <section class="career">
            <h2 class="icon">Works</h2>
              <p><span>草枕</span><br>
              山路を登りながら、こう考えた。<br>
              智に働けば角が立つ。情に棹させば流される。意地を通せば窮屈だ。とかくに人の世は住みにくい。住みにくさが高じると、安い所へ引き越したくなる。どこへ越しても住みにくいと悟った時、詩が生れて、画が出来る。</p>
        </section>
      </div>

で、HTMLだととにかく縦方向にしか進まないので、横方向にレイアウトしたいときに便利なのがCSSのfloatプロパティです。

スクリーンショット 2020-12-05 21.39.07.png

上の画像のように、プロフィール内のテキスト部分を左に、画像を右に寄せていい感じのレイアウトにしたかったのですが…
自分が最初に辿り着いたのは、以下のような状態でした。

スクリーンショット 2020-12-05 21.42.51.png

ヘッダー部分はうまいこと左右がいい感じになったのですが、ボディー部分のレイアウトが崩れてしまったのです……
こういう場合に、clearfixが役立ちます!

そもそもなぜfloatはレイアウト崩れるの?:親要素の高さがなくなるから

floatでレイアウトが崩れるのは、親要素の高さがなくなるからです。
(ヘッダーは親要素の高さをあらかじめ決めていますが、ボディー部は高さを決めておくことってなかなかないですよね)
もともと親要素は、内包する子要素に合わせて高さを変えられます。

advCal01.png

しかしfloatプロパティを適用すると、文字通り親から子が浮いてしまいます。

advCal02.png

今回のようなレイアウトだと、プロフィールセクション内は左のプロフィール文と右の写真しか子要素を持たないため、両方浮かせてしまうと、親要素は高さゼロになってしまいます。

advCal03.png

そして、floatは後続の要素を回り込ませる特性があるため、左の文と右の写真の段差に次のレイアウト要素が回り込んでしまっているというわけです。

clearfixどう使うの?:親要素にclearfixで杭を打ち込んで高さを維持する!

さて、ここでいよいよclearfixの登場です!やり方を順を追って説明します。

①HTMLで親要素にclearfixクラスを追加する

      <div class="main">
        <h1>About</h1>
        <section class="profile clearfix"> <!--  ここ!  -->
          <div class="profile-text">
            <h2 class="icon">Profile</h2>
            <p><span>夏目漱石</span><br>
              わし。なんかとてもすごい人。<br>
<!--  後略  -->

②CSSでclearfixに空のボックスを生成する

.clearfix:after {
  content: "";
}

これは何をしているかというと、擬似要素「:after」を利用して、親要素の末尾に空のボックスを置いています。
まだ回り込みは解消されていません。

advCal04.png

③空のボックスをブロックレベル要素にする

.clearfix:after {
  content: "";
  display: block;
}

display: block;を追加して空のボックスをブロックレベル要素にしています。
ブロックレベル要素にすると必ず前後に改行が入り、高さや幅の指定が可能になります。(↔️インライン要素:テキストの一部として扱われるため、改行は入りません)
つまり、前後の要素の回り込みが解消されます。

advCal05.png

④空のボックスのfloatを解除する

.clearfix:after {
  content: "";
  display: block;
  clear: both;
}

最後にclearプロパティを使って、空のボックスにも自動的に適用されていたfloatを解除します。
これにより、空のボックスが杭を打ち込むような形になり、親要素の高さを保てるようになります!

advCal06.png

出来上がりです!
回り込みが解決して、ちゃんとしたレイアウトになりましたね!
お疲れ様でした!

スクリーンショット 2020-12-05 23.24.43.png

おわりに

親要素の高さを保つだけなら、floatしているものと同じ高さの空ボックスを置くなど、いろんな対策があると思うのですが、
擬似要素で必ず親要素の末尾に空ボックスを置く方法であれば、どんな高さのレイアウト部分にも使用できて、再利用性が高いのがすごく便利だなと思いました!さすが老舗の方法…!

あと、図解すると、親要素から「浮く」って何???という疑問が解決して、スッキリしました!
(一応HTMLの本読みながら描きましたが、解釈が間違ってたら教えてくださいmm!)

ここまでお読みいただき、ありがとうございました!

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

PHPによる繰り返し処理(FOREACH)の応用

はじめに

PHP学んで1ヶ月のクソ初心者。
日々の学びを投稿で残していきますわ。

そもそもFOREACHとは

for文のように繰り返しループ処理を行う構文。
foreach が使えるのは配列とオブジェクトだけ。
構造には二種類の構文がある。

①foreach (iterable_expression as $value)
②foreach (iterable_expression as $key => $value)

★オブジェクト・・・現実世界に存在する「もの」や「概念」のこと。

①の実例

$x = [
    "めろん" => "melon", "もも" => "peach", "いちご" => "strawberry"
];

foreach ($x as $fruit) {
    echo $fruit."<br>";
}

①の表示結果

melon
peach
strawberry

繰り返し処理を行わないで、単純に1つの値を連想配列の中から取り出すのであれば、
値を取り出すための「キー」を指定してあげる必要がある。
しかし!!!
FOREACHでは「キー」を指定することなく、値を順番に利用できる?

②の実例

$x = [
    "めろん" => "melon", "もも" => "peach", "いちご" => "strawberry"
];

foreach ($x as $kudamono => $fruit) {
    echo "キーは「".$kudamono."」<br>";
    echo "値は「".$fruit."」<br>";
}

②の表示結果

キーは「めろん」
値は「melon」
キーは「もも」
値は「peach」
キーは「いちご」
値は「strawberry」

連想配列の値を取り出すときに使う時にキー自体を使うことも可能?‍♂️

実例(応用)

htmlにPHPを組み込んで使用したい場合を紹介します?
★一部コーディングは省略している。

<?php
$fruit = [
    [
        'name' => 'めろん',
        'price' => 1000,
        'note' => '夕張メロンを推します'
    ],
    [
        'name' => 'もも',
//省略
        'note' => 'イチゴ狩り多し!'
    ],
]
?>
<!-- 省略 -->
    <?php foreach ($fruit as $fruit){ ?>
    <div class="box">
            <p class="name"><?php echo '果物名:'.'<br>'.$fruit['name'] ; ?></p>
            <p class="price"><?php echo'¥'.$fruit['price'] ; ?></p>
            <p class="note"><?php echo'メモ:'.'<br>'.$fruit['note'] ; ?></p>
    </div>
    <?php } ?>

「fruit as」の後に同じ変数である「fruit」を使っているが、
FOREACHでは、左側の変数を一度別の変数(右側の変数)に入れて
表示というルールがあるため、このようなコーディングとなる。
★同じだからといって「as fruit」を省略してはダメ?‍♀️

表示結果

スクリーンショット 2020-12-22 21.47.14.png

おわりに

FOREACHって面白いね!(小並感)
てか、フルーツ食べたくなりました???

参考サイト

公式はやっぱ神。はっきりわかんだね。
https://www.php.net/manual/ja/control-structures.foreach.php

スペシャルサンクス

会社のみなさん?‍♂️?‍♂️?‍♂️
ありがとうございまーす!

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

typescriptでnumberが自然数かどうか、booleanで返す関数

typescriptで自然数を判別したい

調べると、型でなんとかしようとする記事が目立った。
でもなんかむずそうだから、普通に関数でやろうと思った。

// 自然数だったらtrueを返す
const isNatureNum = (num: number): boolean => num > 0 && isInteger(num);

使い所

cssのプロパティって、自然数しか使えない場面ってある。
自分の場合、grid使うときにrowを制限したいときとか使った。
この実装だとlimitRownull , undefined , 0 , '' らへんは全部grid-auto-rowsになるはず(間違ってたらごめんね)
そもそも型でnumberに絞ってるけどね。

isNatureNum(prop.limitRow)
    ? {
        overflow: 'hidden',
        gridTemplateRows: `${prop.gridHeight}`,
        height: 'auto',
        maxHeight: `calc(${prop.gridHeight} * ${prop.limitRow})`,
      }
    : { gridAutoRows: `${prop.gridHeight}` };

もっといい方法あったら教えてください

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

styled-componentsでdiv要素のwidthを指定する

はじめに

styled-componentsでdiv要素のwidthをpropsで渡す方法の備忘録です。

いきなりですが結論

const StyledSample = styled.div<{ width: number }>`
  width: ${(props) => props.width};
`;

型を指定してあげれば、styled-componentが受け取ったpropsから
アクセスできました。

公式サイトからは、単純な要素(div,button等)とカスタムコンポーネントで
propsの受け取り方が違うみたいなことしか読み取れなかったので、ちょっと苦労しました…
https://styled-components.com/docs/basics#passed-props

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