Quantcast
Channel: CSSタグが付けられた新着記事 - Qiita
Viewing all 8541 articles
Browse latest View live

年末まで毎日webサイトを作り続ける大学生 〜51日目 簡単なお絵かきアプリを作る〜

$
0
0

はじめに

こんにちは!@70days_jsです。

今日は簡単なお絵かきアプリを作ってみました。
といっても、機能は2つです。笑

  1. 線を描画する
  2. 線のサイズを変更する

色の変更や消しゴム機能はありません。
canvas使ってません。

今日は51日目。(2019/12/8)
よろしくお願いします。

サイトURL

https://sin2cos21.github.io/day51.html

やったこと

test3.gif

やったことは2つです。

  1. 線を描画する
  2. 線のサイズを変更する

まずhtmlから(全文)↓

<body><divid="mouseMoveWrapper"><divid="positionDisplay">描画停止中</div><div><div><inputtype="range"min="1"id="range"max="100"step="1"value="1"/><spanid="rangeDisplay">1</span></div></div><divid="mouseMove"></div></div></body>

id=positionDisplayで描画中かどうか表示しています。
id="range"が文字サイズを変更できるバーです。1〜100の調整ができます。
id=mouseMoveで線を描画します。

次にcss(全文)↓

body{margin:0;overflow:hidden;}#mouseMoveWrapper{width:100vw;display:flex;justify-content:center;align-items:center;flex-direction:column;}#mouseMove{height:90vh;width:90vw;border:solid1pxblack;}.dot{position:absolute;background-color:black;width:1px;height:1px;transform:translateY(-50%)translateX(-50%);}

.dotクラスが線を描画してくれるクラスです。
transformをつけているのは、カーソルの位置を中心に線を描き始めるためです。
というのも、線は本当は線ではなくてdivで作っており、これがないとカーソルの位置にdivの左上端の部分がきて、ずれているように見えるからです。

最後にJavaScriptです。
長いですが載せます。(全文)↓

letmouseMove=document.getElementById("mouseMove");letpositionDisplay=document.getElementById("positionDisplay");letrangeWidth=1;letrangeHeigt=1;letx;lety;letflag=false;mouseMove.addEventListener("mousedown",function(){flag=true;});mouseMove.addEventListener("mouseup",function(){flag=false;});mouseMove.addEventListener("mousemove",function(e){drawStatusDisplay();if(flag){x=e.pageX;y=e.pageY;letdiv=document.createElement("div");div.setAttribute("class","dot");div.style.top=y+"px";div.style.left=x+"px";div.style.width=rangeWidth+"px";div.style.height=rangeHeigt+"px";mouseMove.appendChild(div);}});functiondrawStatusDisplay(){if(flag){positionDisplay.innerHTML="描画中";}else{positionDisplay.innerHTML="描画停止中";}}// _____ここからステータスバー_______letrange=document.getElementById("range");letrangeDisplay=document.getElementById("rangeDisplay");letdotElements=document.getElementsByClassName("dot");functionrangeChange(){rangeDisplay.innerHTML=range.value;rangeWidth=range.value;rangeHeigt=range.value;}range.addEventListener("input",rangeChange);

mousedownとmouseupでマウスを押しているかどうかを判定しています。
押していたらflag変数にtrueを入れ、押していないときはfalseが入っています。

このflag変数を使い、drawStatusDisplay()関数で描画中かどうかを表示しています。

また、描画そのものに関してもこのflag変数を使うことで、マウスが押されていると描画、押されていないと描画しないという風にしています。↓

mouseMove.addEventListener("mousemove", function(e) {
drawStatusDisplay();
if (flag) ←コレ!

rangeについては、rangeWidthとrangeWidthという変数を用意し、描画にもそれを使うことでサイズの変更を実現しています。

他に調べたこと

実は今日promiseで何か作ろうと思っていました。
ですが、なかなか理解できなくて断念。
というわけで、途中までですが調べたことをアウトプットしておきます。

[x] 前提
- JavaScriptはシングルスレッド
- コールバック関数・・・関数が関数を呼び出すこと

[x] 同期処理と非同期処理の違い
- 同期処理・・・記述順に実行する(varとか一部違うけど)
- 非同期処理・・・処理の順番はシャッフル化、実行は1つずつ(ex: イベント処理)

[x] 並列処理と非同期処理の違い
- 並列処理・・・マルチスレッド
- 非同期処理・・・シングルスレッド(ex: promise)

[x] なぜpromise?
- 非同期処理でコールバックを多用すると読みづらい
- → 順序がめちゃくちゃだから
- → 同期的に書こう
- → つまりpromiseとは、実行は非同期処理で、読み方は同期処理

[x] promiseの特徴
- 非同期の関数は本来返したい戻り値の代わりに、呼び出し元にpromiseオブジェクトを返しておく
- 実行できるようになったら、呼び出し元にpromiseオブジェクトを通して値を渡す

[x] JavaScriptのスレッドでやらなくても良い仕事
- タイマー処理
- HTTP通信
- DB周りの処理

感想

divで線を作ると綺麗に書けなかったので、お絵かきアプリを作るならやっぱりcanvasなのかなぁとか思いました。
あと、promise難しい。でも頑張る。

参考

  1. JavaScriptの非同期処理を並列処理と勘違いしていませんか? - Qiita

ありがとうございます!


Lottie入門(WEB)

$
0
0

この記事を読むと3分でLottieを使った可愛いアニメーションにウェブサイトに導入することができます。
snowman.gif

Lottieとは?

概要

Lottieとは LottieはAirbnbが公開しているアニメーションを表示するためのライブラリです。 ... Lottieで表示するアニメーションは、Adobeの「After Effects」を使って作成し、「Bodymovin」というプラグインを使ってアニメーションファイルを出力します。

引用元: Web Design Trends/Web上でアニメーションを表示するなら「Lottie」がおすすめ!特徴や使い方など
https://webdesign-trends.net/entry/10360

一行コードを追加するだけで、高品質なアニメーションを表示できる便利ものです。

いやAfter Effects知らんし!?っていう人も大丈夫

他の人が作ったアニメーションを無料・有料で入手できるプラットフォームがあります。
今回はここから無料の素材を拝借して、導入方法を説明していきます。

LottieFiles
https://lottiefiles.com/featured

では早速はじめていきます。

1分目:好みのアニメを選ぶ

世界中のクリエイターが投稿しているので、いろんな種類のアニメがあります。
好きなアニメをクリックして、出てきたPOPUPのHTMLというボタンを押しましょう。
他にもiOSやAndroid用のコードもありますが、今回はWEBなので、HTMLを選びます。

screencapture-lottiefiles-featured-2019-12-08-21_46_02.png

2分目:詳細ページでLottieをカスタマイズ

詳細ページに行くとwidthやheightを含む細かいパラメータを調整できます。
再生ボタンとかを表示するためのControlはいらないのでoffにしておきましょう。

lottie.png

3分目:HTMLコードをコピペ

あとは、コードをコピーして、自分のプロジェクトに貼り付けるだけです。
簡単ですよね?

snowman.gif

index.html
<linkhref="https://fonts.googleapis.com/css?family=Carter+One&display=swap"rel="stylesheet"><h1>
    Merry Almost Christmas
</h1><script src="https://unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player.js"></script><lottie-playersrc="https://assets9.lottiefiles.com/packages/lf20_VNo3hY.json"background="transparent"speed="1"style="width: 300px; height: 300px;"loopautoplay></lottie-player><style>body{margin:0;padding:120px20px0;background-color:darkred;color:#fff;text-align:center;display:flex;flex-direction:column;align-items:center;height:100vh;font-family:'Carter One',cursive;}</style>

最後に

ちょっとしたアニメーションを加えるだけで、WEBSITEがそれっぽく見えますよね。
是非使ってみてください。

いやAfter Effects知ってるしっていう人は、この記事がおすすめです!

Lottieを利用したアニメーション作成 & 実装
https://qiita.com/Seil/items/d7c363f63e447524dcc7

FloatとFlexboxについて

$
0
0

はじめに

中一日でAdventcalendarの日がまわってQiita!
今回は、自分がいまいち理解できなかったFloatとFlexboxの違いについてまとめてみました。

本題

みなさんは、要素を横並びにするときに何を使っていますか??
FloatFlexbox,FloatにFlexboxなどなどさまざまな方法があると思います。
ということで今回は、FloatとFlexboxって、なにがちがうの?どっちの方を使ったほうがいいのかという2つの観点に目を向けて記事を書いていこうと思います。

今回はFloat・Flexboxを用いて下記のような表示をさせるためにコードを記述していきます。

advent.png

Float

<body>
        <style>
<!-- ブラウザが持っているCSSをリセットするため -->
            * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
            }
            .cleafix::after {
                content: "";
                display: block;
                clear: both;
            }
            .test {
                width: 400px;
                height: 300px;
                margin: 0 auto;
                padding: 5px;
                background-color:aqua;
            }
            .box_A {
                width: 100px;
                height: 100px;
                margin-right: 5px;
                background-color: blue;
                float: left;
            }
            .box_B {
                width: 100px;
                height: 100px;
                margin-right: 5px;
                background-color: yellow;
                float: left;
            }
            .box_C {
                width: 100px;
                height: 100px;
                margin-right: 5px;
                background-color: red;
                float: left;
            }
            footer{
                width: 400px;
                height: 100px;
                margin: 0 auto;
                background-color: purple;
            }
        </style>
        <div class="test clearfix">
            <div class="box_A"></div>
            <div class="box_B"></div>
            <div class="box_C"></div>
        </div>
        <footer></footer>

    </body>

    Points

  1. .clearfix::after{}により、回り込みを防ぐ

  2. `::after` セレクタ要素の直後にスタイルや要素を追加するもの

  3. `content: "";` floatされた要素の親要素の直後に空白の要素を挿入

  4. `display: block;`: contentプロパティによって挿入された空白を横いっぱいに伸ばし、壁のようにする。

  5. `clear:both;`: displayプロパティによって作成れた壁にfloatの回り込みを解除するための機能を与える。

  6. `float:left;`: floatさせたい要素にfloatプロパティを記述する。

以上の2点により、Floatプロパティを用いて、要素を横並びにすることができます。

Flexbox

<body>
        <style>
            * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
            }
            .f-container {
                width: 400px;
                height: 300px;
                margin: 0 auto;
                padding: 5px;
                display: flex;
<!-- conteiner(親要素に使用できるプロパティを紹介したいがために書いたおまけ -->
                flex-flow: row wrap;
                background-color: aqua;
            }
            .item_A {
                width: 100px;
                height: 100px;
                margin-right: 5px;
                background-color: blue;
            }
            .item_B {
                width: 100px;
                height: 100px;
                margin-right: 5px;
                background-color: yellow;
            }
            .item_C {
                width: 100px;
                height: 100px;
                background-color: red;
            }
            footer {
                width: 400px;
                height: 100px;
                margin: 0 auto;
                background-color: purple;
            }
        </style>
        <div class="f-container">
            <div class="item_A"></div>
            <div class="item_B"></div>
            <div class="item_C"></div>
        </div>
        <footer></footer>
    </body>

Points

  • Floatでは、小要素にFloatプロパティを書き、回り込みを防ぐために、`.clearfix::after{}`を記述していましたが、Flexboxでは、親要素に`display:flex`と記述するだけで、Floatと同じような表示ができます。

  • 親要素に`flex-flow: row wrap;`という記述をしていますが、これは、itemの並び順と折返しを一括指定しています。今回表示させたいものには、直接関係はありませんが、親要素のコンテナに使用できる便利なプロパティとして紹介させていただきました。

詳しい情報はこちらから

まとめ

近年では、上記で記したようにflexboxのほうが、非常に簡単に要素を横並びにすることができます。
みなさんもぜひ、Flexboxを使って楽にコードを書いてみてはいかがでしょうか。

参考資料

こちら(flexbox):https://webdesign-trends.net/entry/8148

OSSのプリザンターにSVGテキストアニメーションを入れてみた!

$
0
0








SVGとCSSの勉強がてらプリザンターで遊んでいたら割と良さげなものが出来てしまったのでサクッとまとめていこうかなと思います。

プリザンターとは?

プリザンターとは株式会社インプリムが開発しているオープンソースのWebデータベースです。
データ管理やら業務アプリがマウス操作だけ(ノンプログラミング)でサクッと作れてしまう超有能なプラットフォーム(しかもOSSなので無料という!)なのですな。


オープンソースで脱エクセル!Pleasanter公式サイト


本体コードも自由に変えられるし、スタイルやスクリプト等の拡張機能も豊富なので個人的には勉強した内容を試す場としても最適だと思うんですよね~。

SVGテキストアニメーションを入れてみた!

ということで、アニメーションを入れていきましょう!

"Hello, Pleasanter!"の表示

Implem.Pleasanter/Implem.Pleasanter/Models/Sites/SiteUtilities.csのSiteTopメソッドに追記しています。

コピー用として追記した赤枠の部分を以下に記載します。

Implem.Pleasanter/Implem.Pleasanter/Models/Sites/SiteUtilities.cs
Svg(id:"helloPleasanter",action:()=>hb.SvgText(text:"Hello, Pleasanter!",x:270,y:300),_using:!siteConditions.Any());

あとでCSSでいじるためにidを"helloPleasanter"と設定しています。
x、y項目は位置を、_using項目は表示する条件を表しています。

アニメーション

Implem.Pleasanter/Implem.Pleasanter/Styles/Site.cssに追記しています。

Implem.Pleasanter/Implem.Pleasanter/Styles/Site.css
#helloPleasanter{width:2000px;height:1000px;}#helloPleasantertext{stroke:black;fill:black;font-size:150px;font-style:italic;stroke-dasharray:1400px;stroke-width:1px;-webkit-animation:stroke-anim8slinear;animation:stroke-anim8slinear;}@-webkit-keyframesstroke-anim{0%{stroke-dashoffset:1400px;fill:transparent;}50%{fill:transparent;}100%{stroke-dashoffset:0%;fill:black;}}@keyframesstroke-anim{0%{stroke-dashoffset:1400px;fill:transparent;}50%{fill:transparent;}100%{stroke-dashoffset:0%;fill:black;}}

stroke-dasharrayだけだと破線になってしまうので、stroke-dashoffsetでその破線の位置を動かしていきます。keyframesが100%に近づくとともにstroke-dashoffsetを0%にしていくことで最終的に文字が出来上がるという流れですな。
おまけにfill: blackで塗りつぶすという感じ。

(よくよく思ったんですが、これkeyframesの50%部分は書く必要なかった気もしますがそこはまあ良いとしましょうww)

おわりに

以上でSVGテキストアニメーションの内容は終わりです。
上手く動くとこんな感じのアニメーションになるはず!
SVGアニメーション.gif



今後はこれを応用して手書きの似顔絵っぽいやつ→その人の写真が出る的なのも作ってみたいな~と思っています。


ではでは!また!

初学者が簡単にコーディング練習する方法

$
0
0

こんにちは、たか(@HighHawk5)です。

普通はローカル(自分のパソコン)に開発環境を用意してコーディングしますが、面倒だったりできない場合に便利なのがクラウドIDE。ブラウザ上で簡単にコーディング&表示確認ができます。

今回は数あるクラウドIDEのなかでも一番ライトに使えるCODEPENをご紹介します。

メリット
・開発環境の構築が不要
・色々なエンジニアの作品を参考にできる

See the Pen 三次元回転体 by たかたか (@koutaka) on CodePen.

これは私のpenですが、このようにコーディング&表示確認が一画面でできて便利ですよね!
右上のCODEPENアイコンから本サイトに移動し、メニューの「Fork」をクリックすると、私の作品をあなたのワークスペースにコピーしてコーディングすることもできます。模写がボタン一発で!

Vue.jsはこちらのサンプルなんていかがでしょう?

See the Pen Credit Card Form - VueJs by Muhammed Erdem (@JavaScriptJunkie) on CodePen.

コーディングの上達方法は、見本のコードを模写してイジり倒すこと!

では、より良いエンジニアライフを!

おしまい

box-shadowで月の表現

$
0
0

最終成果物

これです。
ぽいですね。
これがbox-shadowプロパティで実現できます。

moon.gif

実装

土台になるhtmlの用意

さっくりと。

moon.html
<!DOCTYPE html><htmllang ="ja"><head><linkrel="stylesheet"href="../css/moon.css"></head><body><mainclass="stage"><divclass="moon"></div></main></body></html>

CSS

こちらもさっくりと。
解説はあとあと。
stageはただの背景なのでそんなに気にしなくていいです。

moon.css
/**
* stage
*/.stage{position:absolute;width:100%;height:100%;background-color:rgb(228,217,210);display:flex;justify-content:center;align-items:center;}.stage:before,.stage:after{position:absolute;content:"";display:block;}.stage:before{top:20px;left:20px;width:calc(100%-40px);height:calc(100%-40px);border:solid5px#6e5c60;border-radius:30px;box-sizing:border-box;opacity:0.3;}/**
* moon
*/.moon{width:500px;height:500px;border-radius:100%;animation:anime5slinearinfinite;}@keyframesanime{from{box-shadow:none;}to{box-shadow:500px-200px00rgb(254,228,137)inset;}}

ちょっとだけ解説

実際のイメージとは逆かもですが、黄色の明るい部分がbox-shadowで表現されている部分です。
keyframesで定義されている通り、影がない状態から影がある状態にアニメーションさせています。
円形に別のオブジェクトを重ねようとするとどうしても線形な変化になってしまうので、自身に影をつけることで変化させます。
当然外側に影をつけても月にはならないので内側に変化させるためにinsetをbox-shadowにつけるのを忘れずに。

まとめ

box-shadowを内側につけるのは何かと使う場面がありそうですね。
意識していないと忘れてしまいそうなプロパティなのでたまに使ってあげましょう。

HTML CSS Flexboxとは

$
0
0

要素を並べるのにfloat: left;使ってるけど、他にも並べる方法ないかなあ:thinking:

参考サイト→https://www.webcreatorbox.com/tech/css-flexbox-cheat-sheet#flexbox1
随時更新します

Flexboxを使ってみよう

FlexboxとはFlexible Box Layout Moduleの略。左から順に並べられるのは勿論、右からや下からなど自由に要素をレイアウト出来る。

基本

flex_box01.html
<!DOCTYPE html><htmllang="ja"><head><metacharset="utf-8"><title>ブロックとインライン</title><linkrel="stylesheet"href="css/flex_box01.css"></head><body><divclass="container01"><divclass="item">アイテム&ensp;1
    </div><divclass="item">アイテム&ensp;2
    </div><divclass="item">アイテム&ensp;3
    </div><divclass="item">アイテム&ensp;4
    </div></div></body></html>
flex_box01.css
.container01{display:flex;}.item{margin:10px10px;padding:2px4px;background:#f8dcdc;}

20191129_Qiita01.png
display: flex;を親要素に適用し、子要素が横に並んだ。

Flexboxで親要素に指定するプロパティ

htmlは上と同じ。

flex-direction: row;

flex_box02.css
.container01{display:flex;flex-direction:row;}.item{~省略~}

20191129_Qiita02.png
右から左へ並ぶ

flex-direction: row-reserve;

flex_box03.css
.container01{display:flex;flex-direction:row-reverse;}.item{~省略~}

20191129_Qiita03.png
左から右へ並ぶ

flex-direction: column;

flex_box04.css
.container01{display:flex;flex-direction:column;}.item{~省略~}

20191129_Qiita04.png
上から下へ並ぶ

flex-direction: column-reverse;

flex_box05.css
.container01{display:flex;flex-direction:column-reverse;}.item{~省略~}

20191129_Qiita05.png
下から上へ並ぶ

flex-wrap: nowrap;

説明のために数を増やした

flex_box02.html
<!DOCTYPE html><htmllang="ja"><head><metacharset="utf-8"><title>ブロックとインライン</title><linkrel="stylesheet"href="css/flex_box.css"></head><body><divclass="container02"><divclass="item">アイテム&ensp;1
    </div><divclass="item">アイテム&ensp;2
    </div><divclass="item">アイテム&ensp;3
    </div><divclass="item">アイテム&ensp;4
    </div><divclass="item">アイテム&ensp;5
    </div><divclass="item">アイテム&ensp;6
    </div><divclass="item">アイテム&ensp;7
    </div><divclass="item">アイテム&ensp;8
    </div><divclass="item">アイテム&ensp;9
    </div><divclass="item">アイテム&ensp;10
    </div></div></body></html>
flex_box06.css
body{~省略~}.container02{margin:10pxauto;display:flex;flex-wrap:nowrap;}.item{~省略~}

20191129_Qiita06.png
折り返しなしで一行で並ぶ

flex-wrap: wrap;

flex_box06.css
body{~省略~}.container02{margin:10pxauto;display:flex;flex-wrap:wrap;}.item{~省略~}

20191129_Qiita07.png
子要素が折り返して複数行になり、上から下へ並ぶ

flex-wrap: wrap-reverse;

flex_box07.css
body{~省略~}.container02{margin:10pxauto;display:flex;flex-wrap:wrap-reverse;}.item{~省略~}

20191203_Qiita01.png
子要素が折り返して複数行になり、下から上へ並ぶ

flex-flow: ;

flex_box08.css
.container02{margin:10pxauto;display:flex;flex-flow:row-reversenowrap;}

flex-directionflex-wrapを一行で指定できるプロパティ。

justify-content: flex-start;

flex_box09.css
.container02{margin:10pxauto;display:flex;justify-content:flex-start;}

20191203_Qiita02.png
10個だと分かりにくかったので5個にした。親要素に空いているスペースがあるとき、子要素を水平方向のどの位置に置くか指定
flex-startは左揃えになる。

justify-content: flex-end;

flex_box10.css
.container02{margin:10pxauto;display:flex;justify-content:flex-end;}

20191203_Qiita03.png
flex-endは右揃えになる

justify-content: flex-center;

flex_box11.css
.container02{margin:10pxauto;display:flex;justify-content:flex-center;}

20191203_Qiita04.png
flex-centerは中央揃えになる

justify-content: space-between;

flex_box12.css
.container02{margin:10pxauto;display:flex;justify-content:space-between;}

20191203_Qiita05.png
最初の子要素を左端、最後の子要素を右端に配置し、残りの要素は均等に間隔をあけて配置

CSSだけで動的サイトを作れるらしい!!

$
0
0

はじめに

最近まで深層学習の技術ブログを書いていたが、心機一転してWeb系の勉強に戻ることにした。
今までは安定を求めてAIを数ヶ月勉強していたけど面白くなかった。
やはり楽しいほうがいいと思ったので今回Web系に戻ろうと思う。

CSSだけで動的サイトを作る

今まで動的サイトといえばJavaScriptを使わないといけないと思っていたが、実はJavaScriptから提供された変形とアニメーションの機能がCSSにあるらしい。
聞くところによればJavaScriptよりも高速に動くらしいのでこれから是非使っていきたいと思う。

transformプロパティ

cssでtransformプロパティを使うことで、移動・拡大縮小・回転・傾斜の変形を行うことができる。
これらの変形を行うには、transformプロパティで、各トランスフォーム関数をして営してあげることで行うことができる。

transelate(x軸の移動,y軸の移動)
translate関数を使うことで、x軸y軸の移動を行うことができる。
上の様にx軸とy軸の移動する距離を指定してあげることで要素を移動することができる。

scale(x軸方向の倍率,y軸方向の倍率)
scale関数を使うことで要素のx軸y軸方向の拡大縮小が可能です。

rotate(回転角度)
rotate関数で要素を回転させることができます。
どれだけ回転させるかは、角度を指定することで決められます。

skew(x軸の傾斜角度,y軸の傾斜角度)
skew関数で要素に傾斜をつける変形を行うことができます。


CSSサブグリッドで真のフレキシブルなレイアウトを実現する方法

$
0
0

2019年12月3日、Firefox71がリリースされ、このバージョンから CSS Subgridが使用できるようになりました。
CSS Subgridは2016年来からW3CのWorking Draftによって勧告されていましたが、今回のFirefoxのアップデートによって遂にユーザーへ提供できるようになりました。
この記事では、CSS Subgridの何が我々をワクワクさせ、どのようにインタフェースの実装を変化させてくれるのかについて紹介したいと思います。

CSS Subgrid とは

CSS Gridのおさらい

CSS Subgridの説明の前に、簡単にCSS Gridのおさらいをします。
CSS Gridとは、2次元レイアウトをCSSを用いて簡潔に組むための仕組みを指します。
任意の要素にdisplay: grid;を適用することで、以下の画像のように対象の要素はグリッドコンテナーとして、グリッドコンテナーの子要素はグリッドアイテムとして扱われます。
Group.png

<ulstyle="display: grid;"><!-- グリッドコンテナー --><li>ぺんぎん</li><!-- グリッドアイテム --><li>あざらし</li><!-- グリッドアイテム --><li>らっこ</li><!-- グリッドアイテム --></ul>

CSS Gridの問題点

CSS Gridを用いることで、グリッドアイテムの高さを柔軟に揃えることが可能となりました。
では、我々の戦いはGridの登場によって終わりを迎えたのでしょうか。

そんなことはありません。グリッドアイテムの中の要素に目を向けるとどうでしょう。
グリッドアイテムの中には画像やテキスト等の複数の要素を設ける必要があります。これらのテキストはコンテンツによって変化するため、実装時には様々な高さへ変化することを想定しなくてはいけません。

しかしながら、グリッドアイテムは以下の画像のように、中の要素の高さまでは揃えることができません。
Group 2.png

CSS Subgridの登場

この問題を解決してくれるのがCSS Subgridです。
詳細な実装方法は後述しますが、グリッドアイテム要素に対してgrid-template-columns: subgrid;grid-template-rows: subgrid;を指定することで、CSS Subgridを有効化させることができます。
有効化させることで、グリッドアイテムの中の要素をサブグリッドアイテムとして扱うことができ、アイテム毎に高さを可変させることが可能となります。

以下の例ではSubgridを用いてタイトル部分の高さを可変させています。Subgrid未適用時は高さがコンテンツ毎に異なっているのに対し、Subgrid適応時は高さが統一されてるかと思います。

未適用時適用時 (Firefox 71)

Subgridを自在に操ることで、真のフレキシブルなレイアウトを簡潔に実現することが可能となります。

対応環境 (2019/12/07現在)

現在はFifefox 71~ のみ対応しています。
image.png
Subgrid | Can I Use...より

使い方

サンプル

See the Pen Sample of CSS Subgrid by oreo (@oreo) on CodePen.

(Firefox 71~で確認してみてください。)

実装方法

Subgridは以下のソースコードで対応することが可能です。

<ulclass="gridContaienr"><liclass="gridItem"><imgsrc="https://via.placeholder.com/150"alt=""><h3>タイトル</h3><p>テキスト</p><ahref="http://example.com/">リンク</a></li><liclass="gridItem"><imgsrc="https://via.placeholder.com/150"alt=""><h3>タイトル</h3><p>テキスト</p><ahref="http://example.com/">リンク</a></li><liclass="gridItem"><imgsrc="https://via.placeholder.com/150"alt=""><h3>タイトル</h3><p>テキスト</p><ahref="http://example.com/">リンク</a></li></ul>
.gridContainer{display:grid;grid-template-columns:repeat(3,minmax(200px,1fr));grid-gap:1em;}/* 以下の記述を追加 */.gridContainer.gridItem{display:grid;grid-row:span4;grid-template-rows:autoauto1frauto;/* fallback for non-supported browsers */grid-template-rows:subgrid;}

まずは.gridItemdisplay: grid;を指定することでグリッドコンテナーとして扱う必要があります。
同時に、grid-template-rows: subgrid;を指定することで、グリッドコンテナーをサブグリッド化することができます。

こちらの例ではSubgridに対応していないブラウザ用のフォールバックとして、grid-template-rows: auto auto 1fr auto;を指定しています。
可変させる要素と固定させる要素を明示することで、Subgridに対応していないブラウザでも最低限のレイアウトを担保できるので、未サポートブラウザが多い現在はこちらの記述も必須でしょう。

終わりに

CSS SubgridはFlexやGridだけでは実現できなかったレイアウトを簡潔に実現できる力を秘めていると考えられます。
現在はFirefoxのみが対応していますが、今後より多くのメジャーなブラウザへの実装され、ユーザーへ提供できるようになることを願ってやみません。

参考サイト

はじめてぶらうざののべるげーむをつくってみたの!

$
0
0

はじめてぶらうざののべるげーむをつくってみたの!

自分でノベルゲーを作りたくなったので、モチベ維持のためにもQiita記事にしました。
ゆくゆくは簡単にブラウザノベルゲームを作れるソフトでも作りたいなと思ってるので、その下調べ的ななにがしですね。

Qiita記事は初心者なので、なんか書いた方がいいこととかあれば教えてくだせぇ。
それではさっそく行きましょう。

Chapter 0.使用言語

  • HTML
  • CSS
  • JavaScript(JQuery)

Chapter 1.とりあえずタイトル画面つくるかのぅ…。

タイトル画面がないと始まりません。

1.仮でとりあえず作っていきます。

StartMenu.jpg

html
<body><h1>ノベルゲーム!</h1><ahref="">続きから</a><ahref="">最初から</a><ahref="">環境設定</a></body>
css
*{text-decoration:none;color:black;}h1{background-color:rgba(255,0,0,.3);}a{display:block;background-color:rgba(0,255,0,.3);}

必要なものはこれくらいでしょうか。
これをもとにCSSでデザインを作っていきますが、上の通りbackground-color:rgba(??,??,??,.3);などと背景色をつけるとどの要素がどこにいるかわかりやすいですね。

2.タイトルとメニューは中央寄せにしたいですね。

そこで、text-align:center;をh1とaに対して指定します。
また、それぞれのwidthを10emにしました。
Div2.jpg
この時点では、h1要素とa要素の中身は中央寄せになりましたが、a要素自体は左に寄っています。これを真ん中に持ってくるためにdisplay:flex;を召喚します。

html
<divid="felxcontainer"><h1>ノベルゲーム!</h1><ahref="">続きから</a><ahref="">最初から</a><ahref="">環境設定</a></div>
css
#flexcontainer{display:flex;flex-flow:columnnowrap;align-items:center;position:absolute;top:0;bottom:0;left:0;right:0;}

すると
StartMenu3.jpg
無事真ん中に来ました。

3.背景がなんか寂しいなぁ…。

というわけでネットのフリー画像を背景に指定。

css
body{background:url("image/TopImage.jpg");margin:0;padding:0;position:absolute;top:0;bottom:0;left:0;right:0;}

StartMenu4.jpg

全体的に上に寄っているので、h1とaの親要素(#flexcontainer)のcssに、justify-content:center;を追加します。すると以下の通り全体が真ん中に来ます。
StartMenu5.jpg

4.あとはこまごま調整して…

最終的にはこんな感じになりました。
StartMenu6.jpg

html
<body><divid="flexcontainer"><h1>ノベルゲーム!</h1><div><ahref="">続きから</a><ahref="">最初から</a><ahref="">環境設定</a></div></div></body>
css
*{text-decoration:none;color:black;}body{background:url("image/TopImage.jpg");margin:0;padding:0;position:absolute;top:0;bottom:0;left:0;right:0;}#flexcontainer{display:flex;flex-flow:columnnowrap;align-items:center;justify-content:center;position:absolute;top:0;bottom:0;left:0;right:0;}#flexcontainerdiv{border:2pxsolidwhite;border-radius:5px;}h1{margin:0;color:white;font-size:11vw;text-align:center;}a{color:white;display:block;text-align:center;font-size:2.5vw;line-height:2em;width:10em;}a:hover{background-color:rgba(255,255,255,.5);}

根気が残っていれば次回以降はゲームの中身の部分を作っていく予定です。


参考サイト

  • PAKUTASO(ここのフリー画像を使いました。)

jQueryプラグインの実践

$
0
0

jQueryプラグインの実践をしてみた

こんにちは。ちょっとずつ学習したことを実践して投稿します。

やったこと

jQueryとjavaScriptを使って、
1. 画像をクリックしたら、そのフォントサイズを表示する。
2. ボタンをクリックしたらテキストを取得し表示する

コード

部分的にコードを抜粋します。
index.htmlに画像などいろいろと要素を埋め込んでいきます。
jquery.showsize.jsの方へ画像をクリックした際の動作を埋め込んでいき、外部ファイルとして取得します。

index.html
<buttontype="button"name="button"><p><imgsrc="img/hoge.jpg"></p><divid="cat1-button"><pid="text-a">click</p></div></button><buttontype="button"name="button"><p><imgsrc="img/hogehoge.jpg"></p><divid="cat2-button"><pid="text-b">click</p></div></button><buttontype="button"name="button"><p><imgsrc="img/hogehogehoge.jpg"></p><divid="cat3-button"><pid="text-c">click</p></div></button><buttontype="button"name="button"><p><imgsrc="img/hogehogehogehoge.jpg"data-size="30"></p><divid="cat4-button"><pid="text-d">click</p></div></button></div></ul><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script><script src="jquery.showsize.js"></script><script>$(function(){$('img').showsize({});});{document.getElementById("cat1-button").onclick=function(){document.getElementById("text-a").innerHTML="hoge";};}{document.getElementById("cat2-button").onclick=function(){document.getElementById("text-b").innerHTML="hogehoge";};}{document.getElementById("cat3-button").onclick=function(){document.getElementById("text-c").innerHTML="hogehogehoge";};}{document.getElementById("cat4-button").onclick=function(){document.getElementById("text-d").innerHTML="hogehogehogehoge";};}</script></div>
jquery.showsize.js
;(function($){$.fn.showsize=function(options){varelements=this;elements.each(function(){varopts=$.extend({},$.fn.showsize.defaults,options,$(this).data());$(this).click(function(){varmsg=$(this).width()+' x '+$(this).height();$(this).wrap('<div style="position:relative;"></div>');vardiv=$('<div>').text(msg).css('position','absolute').css('top','0').css('background','black').css('color',getRandomColor()).css('font-size',opts.size+'px').css('opacity',opts.opacity).css('padding','2px');$(this).after(div);});});returnthis;};functiongetRandomColor(){varcolors=['white','skyblue','orange','green'];returncolors[Math.floor(Math.random()*colors.length)];}$.fn.showsize.defaults={size:10,opacity:0.9};})(jQuery);

後記

複数のscriptが続く際には、{}で括るという初歩的なことが大事だと痛感しました。
このコードをサンプルとしてご自由にご利用ください。

技術ポートフォリオを作った話

$
0
0

つい先月,自分のgithubアカウントで技術ポートフォリオを作成した.→ tackkyのポートフォリオ
どうしてgitもhtmlも慣れていないのに作ろうと思ったのか,その辺の話も含めて記事にする.

技術ポートフォリオは何に役立つ?

1. 就活で使える

1. 逆求人

これが一番大きい. 特に最近IT系の就活では逆求人(企業様の方から連絡が来る就活)で,まず自分の情報を見ていただく.

例えば,

  • 研究室での研究内容
  • 資格,その他技術的にやってきたこと

など.この場合,研究内容だけ突き詰めて研究している方ならそこを詳しく書けばいいけれど,私などのようにいろんな技術をつまみ食いしているような人には不利になる.githubで公開リポジトリーとしてアップするという手もあるけれど,やはり就活では技術に詳しくない人事の方も見ているので,見た目にも綺麗なwebページが一番企業様へのインパクトは大きい.

2. エントリーシート

このような目的で作成されたポートフォリオは,エントリーシートの作成にも役立つ.
研究内容にも言及していれば,そのポートフォリオ記事を参考に書くことができるし,アピールポイントにこのページのURLを貼ることができる.(後たまに,技術ポートフォリオがあれば教えてくださいみたいな欄があることがある)

2. 勉強になる

最後に,HTMLとCSSを使うので何より勉強になる.私は研究室や講義でHTMLは兎も角CSSは使用したことはないけれど,技術ポートフォリオを作ることはHTMLとCSSの使用経験につながる.

技術的観点から

GitHub

技術者になる者,Github含め,Gitは使えるようになった方がいい.私は研究を他の人と共同でやっていないので研究室としてgitを使用することはないけれど,バージョン管理システムとして少し前から使い始めた.特に共有する相手がいなくてもgitはおすすめ.よく考えなくてもgitは バージョン管理システムである.私が最近使用しているgitの使い道が参考になるかもしれない.

  • 理由1 論文を書くときにも使える.

    参考URL:ライトに知りたい人はこちらしっかり読みたい人はこちら

    ナウいヤングは論文執筆にGitHubを使う
    まず、学会や学校などのテンプレートを導入して正しくコンパイルされる状態にしたものをfirst commitとしてmasterブランチにコミットします。
    次にmasterから1stブランチを切って、GitHub上でmasterブランチにPull Requestを送ります。
    PRを送ったら、1stブランチでガリガリ初稿を書いていきます。コミットの粒度は小節毎だったり段落ごとだったりしますが、これは執筆が進んでいくと変わっていくと思います。後半になると修正箇所も少なくなるので「○○先生添削分修正」などとふわっとしてきます。
    添削の依頼をして返ってきたら、1stブランチをmasterにマージします。そして2ndブランチを切ってPRを送って……の繰り返しです。

  • 理由2 スライド管理にも使える.
    様々な版(学会用,卒業発表用等)とわけることができる.次のページがわかりやすすぎるので説明は割愛.

    参考URL:ここのページからスライド管理するようになった

HTMLとCSS

…ざっくり仕組み使えるようになりたいなって思ってた,それだけです.講義で扱うのはHTMLだけなのでやっぱり心寂しい.

技術ポートフォリオの作り方

作ってみた流れ.

1.githubでページを作る

GitHub Pagesというサービスがある.これは,Githubに登録したリポジトリーをwebページとして公開することができるGitHubのサービスである.settinggithub pagesの項目があるのでそこでソースをマスターブランチに登録するだけである.とりあえずhello worldとでも書いたindex.htmlを用意して公開すればいい.

一応:github pagesによる静的サービス公開方法

2.サンプルページを探してくる

結構フリーでHTMLとCSSのソースは落ちている.特にtemplate free engineer portfolioとでも検索すれば,ごまんとフリーテンプレートが見つかる.私は以下のサイトから見つけてきた.(確か.)
50 free portfolio website templates 2019

3.自分仕様に変更する

後はダウンロードしたデータを自分仕様にカスタマイズするだけだ.先のテンプレートサイト等には結構な量のデータがあるので,私のような初心者エンジニアにはいらない部分が多すぎる.なので「いらない部分を削る」作業が必要になる.これには,どこからどこまで削っても問題なく動作するのか判断するために,HTMLの構造を理解している必要がある.CSSは色のテイストや配置などを変えたくなってから触る方が楽なのでとりあえず置いておいて,HTMLCSSの順でカスタマイズするのがおすすめ.

おめでとう!

ここまでのプロセスでやっと技術ポートフォリオをつくることができる.新しいことに取り組むことがあれば,どんどん追加して素晴らしいポートフォリオにしよう.

参考サイト

エンジニア向けのポートフォリオサイトまとめ
ポートフォリオをGitHub で公開する

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

$
0
0

100日チャレンジの179日目

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

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

179日目は

年末まで毎日webサイトを作り続ける大学生 〜52日目 JavaScriptで神経衰弱ゲームを作る〜

$
0
0

はじめに

こんにちは!@70days_jsです。

今日は神経衰弱を作りました。

全部クリアすると、なんと!

最後にとっておきの画像を見ることができます!
(大声では言えないですが、思わず興奮してしまう画像です...)

ぜひやってみてください。

ちなみにバグもありまして、素早く連続でクリックすると何枚もカードが開けてしまうのでご了承ください。直す時間がありませんでした。

今日は52日目。(2019/12/9)
よろしくお願いします。

サイトURL

https://sin2cos21.github.io/day52.html

やったこと

外観と動作はこんな感じです。↓
test3.gif

ほぼ全てJavaScriptで作りました。一部cssのアニメーションも使っています。
のでhtmlは何もなし↓

<body></body>

JavaScript長いですが一応全て載せます↓

window.onload=function(){createCardWrapper();//wrapperを作るcreateCard();//cardを作る};letdivWrapper;//一番大枠のdivletcountDisplay;letcountDisplaySpan=document.getElementById("countDisplaySpan");letcard=[{0:""},{1:""},{2:""},{3:""},{4:""},{5:""},{6:""},{7:""},{8:""},{9:""},{10:""},{11:""},{12:""},{13:""},{14:""},{15:""}];//それぞれのcardにつけるidletimage=["1","2","3","4","5","6","7","8"];//cardの画像名letimageNumber=0;letbeforeCard="";//前にクリックしたcardletid;//クリックしたcardのid(=key)letcountClick=2;//1回目か2回目かの判断letgoal=0;//全て当てたかどうかの判断functionclicked(e){open(e);//cardクリック時のモーションsuccessOrFailure(e);}//cardクリック時のモーションfunctionopen(e){id=e.target.id;e.target.classList.add("click-none");e.target.classList.add("card-rotate");delayImageDisplay(1000).then(function(){e.target.style.backgroundImage="url(day52/"+card[id][id]+".png)";e.target.classList.remove("card-rotate");});}functionsuccessOrFailure(e){if(countClick%2==0){//1回目countClick++;countDisplaySpan.innerHTML=countClick-2+", 奇数, 前回のカード"+beforeCard+",ポイント: "+goal;beforeCard=id;}else{//2回目、かつ成功if(card[beforeCard][beforeCard]===card[id][id]){console.log("success");countDisplaySpan.innerHTML=countClick-2+", 偶数, 前回のカード"+beforeCard+",ポイント: "+goal;beforeCard=id;countClick++;goal+=Number(card[id][id]);if(goal===36){setTimeout(goaal,2000);}}else{//2回目、かつ失敗e.target.classList.add("card-rotate");countClick++;countDisplaySpan.innerHTML=countClick-2+", 偶数, 前回のカード"+beforeCard+",ポイント: "+goal;delayImageDisplay(1000).then(function(){e.target.classList.remove("card-rotate");}).then(function(){letbefore=document.getElementById(beforeCard);beforeCard=id;setTimeout(function(){before.style.backgroundImage="url(day52/day52_card.png)";e.target.style.backgroundImage="url(day52/day52_card.png)";console.log(before);console.log(e.target);e.target.classList.remove("card-rotate");e.target.classList.remove("click-none");before.classList.remove("click-none");},1000);});}}}//image配列の順番をシャッフルするfunctionshuffle(){for(vari=image.length-1;i>0;i--){letrandom=Math.floor(Math.random()*(i+1));lettmp=image[i];image[i]=image[random];image[random]=tmp;}}//一番大枠のwrapperを作成する関数functioncreateCardWrapper(){countDisplay=document.createElement("div");countDisplaySpan=document.createElement("span");countDisplaySpan.setAttribute("id","countDisplaySpan");countDisplay.innerHTML="クリック回数: ";countDisplay.appendChild(countDisplaySpan);document.body.appendChild(countDisplay);divWrapper=document.createElement("div");divWrapper.setAttribute("id","divWrapper");document.body.appendChild(divWrapper);}//cardを16枚作る関数functioncreateCard(){shuffle();//画像をシャッフルするfor(vari=0;i<card.length;i++){letdiv=document.createElement("div");letkey=Object.keys(card[i]);//a,b..pと順番に入るdiv.setAttribute("id",key);card[i][key]=image[imageNumber];//cardと画像が結びついた(画像は2枚ずつ)div.setAttribute("class","card");// div.style.backgroundImage = "url(day52/" + image[imageNumber] + ".png)";if(imageNumber>=7){imageNumber=0;shuffle();//画像をシャッフルする}else{imageNumber++;}divWrapper.appendChild(div);div.addEventListener("click",clicked);}console.log(card);}//画像の表示を遅らせるための関数functiondelayImageDisplay(delay){returnnewPromise(function(resolve){setTimeout(resolve,delay);});}functiongoaal(){goalDiv=document.createElement("div");goalImg=document.createElement("img");goalDiv.innerHTML="おめでとうございます!";goalImg.setAttribute("class","goalImg");goalDiv.setAttribute("class","goalDiv");goalImg.setAttribute("src","day52/secret.jpg");goalDiv.appendChild(goalImg);document.body.appendChild(goalDiv);}

cssも一応全て載せておきます。↓

body{margin:0;height:100vh;display:flex;justify-content:center;align-items:center;flex-direction:column;}img{max-width:100%;max-height:100%;}#divWrapper{width:600px;height:auto;background-color:rgba(80,80,200,0.3);display:flex;justify-content:center;align-items:center;flex-wrap:wrap;}.card{display:inline-block;width:130px;height:130px;background-color:rgba(50,50,50,0);/* border: solid 1px black; */margin:1%;background-image:url("day52/day52_card.png");background-size:cover;}.card:hover{opacity:0.2;}.card-rotate{animation:rotate;animation-duration:1s;}@keyframesrotate{0%{transform:rotateY(0deg);}100%{transform:rotateY(92deg);}}.click-none{pointer-events:none;}.goalDiv{position:absolute;background-color:black;width:100vw;height:100vh;display:flex;justify-content:center;align-items:center;color:white;flex-direction:column;font-size:3em;}.goalImg{display:inline-block;}

肝になる部分

ちょっと今回は長いので大事なところだけ説明していきます。

let card = [
...

この変数↑は配列ですが、その中身はhash形式で情報を保存しています。↓

{ 0: "" },
{ 1: "" },
{ 2: "" },
...

神経衰弱のカードにはそれぞれidが割り振られており、このhashのキー(0~15)はそのidと全て対応しています。
このhashはのちにvalueに1~8の値を持ちます。
この数字は画像の名前と一致しており、それぞれ2回ずつhashに割り当てることで対になる2枚のカードを実現しています。
これがhashのvalueに入る数字です。↓

let image = ["1", "2", "3", "4", "5", "6", "7", "8"]; //cardの画像名

このままでは順番通りに画像が入ってしまうので、image配列の中身をシャッフルします。↓

function shuffle() {
for (var i = image.length - 1; i > 0; i--) {
let random = Math.floor(Math.random() * (i + 1));
let tmp = image[i];
image[i] = image[random];
image[random] = tmp;
}
}

promiseを使う

ちなみに、今回promiseも少し使ってみました。
やっぱりまだ理解しきれていないですが。↓

function delayImageDisplay(delay) {
return new Promise(function(resolve) {
setTimeout(resolve, delay);
});
}

function open(e) {
id = e.target.id;
e.target.classList.add("click-none");
e.target.classList.add("card-rotate");
delayImageDisplay(1000).then(function() {
e.target.style.backgroundImage = "url(day52/" + card[id][id] + ".png)";
e.target.classList.remove("card-rotate");
});

ただ、しっかり順番通りに動いてくれているので、なんとなく便利だということは分かりました。
いずれちゃんと理解しようと思います。

ゴールページについて

神経衰弱を全てやり終えたら思わず興奮してしまう画像を用意しています。

変数を用意します。↓

let goal = 0;

カードが当てることができたら、goal変数に画像の値分(0~8)数値を足します。↓

goal += Number(card[id][id]);

画像はは0~8なので、全て足し合わせると36になります。36になると関数を実行するようにしています。↓

if (goal === 36) {
setTimeout(goaal, 2000);
}
} else {...

関数の中身です。secret.jpgが例の画像です。↓

function goaal() {
goalDiv = document.createElement("div");
goalImg = document.createElement("img");
goalDiv.innerHTML = "おめでとうございます!";
goalImg.setAttribute("class", "goalImg");
goalDiv.setAttribute("class", "goalDiv");
goalImg.setAttribute("src", "day52/secret.jpg");
goalDiv.appendChild(goalImg);
document.body.appendChild(goalDiv);
}

secret画像は国宝級の画像を用意しました。
皆さんもぜひ試してみてください!(アプリでは全て見れます)↓
スクリーンショット 2019-12-09 21.54.06.png

感想

ちょっと今日は説明が意味不明すぎることになっていると思います。
申し訳ありません。

というのも、手当たり次第に作っていたら色々と複雑になってしまい、全てを言語化していたら膨大な量になってしまうと判断したからです。
今後は最初にきちんと設計して、なるべくシンプルなコードを書けるように尽力します

最後まで読んでいただきありがとうございます。明日も投稿しますのでよろしくお願いします。

参考

  1. アイコン素材ダウンロードサイト「icooon-mono」 | 商用利用可能なアイコン素材が無料(フリー)ダウンロードできるサイト | 6000個以上のアイコン素材を無料でダウンロードできるサイト ICOOON MONO
  2. パブリックドメインQ:著作権フリー画像素材集

画像を使用させていただきました。

あまり知られていないcalc()とvwを使ったお手軽レスポンシブ制御

$
0
0

この記事は CSS Advent Calendar 2019 10日目の記事です。

はじめに

僕はCSSが大好きで、普段からCSSテクニックやCSSハックなどを探しまくっています。最近ではFirefox69のみに適用されるCSSハックを見つけたりしました。

// Firefox69@supportsselector(_>_)and(not(text-underline-offset:0)){_:-moz-is-html,.selector{property:value;}}

@supportsクエリが実装されたため、CSSハックも探すのが昔と比べてかなり楽になっています。こんな感じでCSSの仕様やバグをついたテクニックを探すのが特に好きです。

さて、今回は実務でも使って欲しいレスポンシブ対応が楽になるテクニックの紹介です。レスポンシブ対応といえば、メディアクエリを使ってブラウザ幅ごとに制御する方法が一般的です。それに対し、毎年登場するデバイスのブラウザ幅は多種多様で今後も増え続けると思われます。そのため、タブレットなら 768px以上、PCなら 992px以上と決めて実装していると、あるブラウザ幅でデザインが崩れている...なんてことになりかねません。

では、メディアクエリを細分化してどのブラウザ幅になっても問題ないようにすれば良いかというと、そうではありません。

body{font-size:15px;}@media(min-width:320px){body{font-size:16px;}}@media(min-width:336px){body{font-size:17px;}}@media(min-width:352px){body{font-size:18px;}}...

これは少し極端な例ですが、あらゆるブラウザ幅に対応するのは無理があります。そこで、便利なのが calc()関数と vw単位です。

calc()関数とvw単位

calc()関数は calc(100% - 100px)のように異なる単位どうしで計算ができます。演算子との間にはスペースを空けておきます。vw単位はブラウザ幅を表しており、100vwがブラウザ幅いっぱいとなります。ブラウザ幅が変化すれば、100vwのときの px値も変化します。50vwとすれば常にブラウザ幅の半分の値となります。ただし、vw単位はブラウザのスクロールバーの幅を含むことに注意が必要です。

1次関数

ブラウザ幅によって変動する vw単位があれば、メディアクエリを細分化することなく値を設定できます。しかし、そのまま vw単位を使おうとするとこのブラウザ幅のときにはこの値になって欲しいといったようなことが難しいと分かります。そこで、calc()関数を使って1次関数にしてしまえば、直感的に指定できるようになります。

まずは、1次関数の定義からです。1次関数は2点の座標 $ (x_1,\ y_1),\ (x_2,\ y_2) $ を通る直線なので、

y = ax + b \quad \left( a = \cfrac{y_2-y_1}{x_2-x_1},\ \ b = y_1 - ax_1 \right) 

と定義されます。ここではブラウザ幅 320pxのときは font-size: 20px、ブラウザ幅 768pxのときは font-size: 40pxとなるように2点 $ (320,\,20),\ (768,\,40) $ をとります。2点が決まったので、$ a,\ b $ の値を求めます。

\begin{align}
a &= \cfrac{40 - 20}{768 - 320} = \cfrac{20}{448} = \cfrac{5}{112}\\
b &= 20 - \cfrac{5}{112} \times 320 = \cfrac{2240 - 1600}{112} = \cfrac{640}{112} = \cfrac{40}{7}
\end{align}

よって、1次関数の式は以下のようになります。

y = \cfrac{5}{112}x + \cfrac{40}{7}

ここで、$ x $ はブラウザ幅を表しているので $ 100\,\mathrm{vw} $ と置き換えられます。

y = \cfrac{5}{112} \times 100\,\mathrm{vw} + \cfrac{40}{7}

これで、1次関数の式が求められたので calc()関数とメディアクエリを使って表現します。

// ブラウザ幅 < 320pxbody{font-size:20px;}// 320px ≦ ブラウザ幅 < 768px@media(min-width:320px){body{font-size:calc((5/112)*100vw+(40/7)*1px);}}// 768px ≦ ブラウザ幅@media(min-width:768px){body{font-size:40px;}}

320px以上 768px未満の間だけ1次関数にして、両端の区間はそれぞれ最小値と最大値が一定になるようにしています。

body{font-size:1.25em;}@media(min-width:20em){body{font-size:calc((5/112)*100vw+(40/7/16)*1em);}}@media(min-width:48em){body{font-size:2.5em;}}

分かりやすいように pxで表記しましたが、できればアクセシビリティを考慮して emremなどの相対値を使うと良いです。また、メディアクエリ部分は px表記なのに、font-sizeemで指定するなど、絶対値と相対値の組み合わせは絶対にしてはいけません。

2次関数

1次関数が使えるだけでも非常に便利ですが、2次関数で曲線が使えるともっと便利だなと思いました。2次関数の一般形は、

y = ax^2 + bx + c

で表されますが、現在のCSSでは $ x^2 $ という部分を表現できません。calc()関数の仕様によると乗算の場合、引数の少なくとも1つがNumber型である必要があります。つまり、$ x^2 $ を表す calc(100vw * 100vw)は両方とも単位付きであるため不正な値となります。仕様上不可能ということが分かったので、1次関数による線形補間で近似することにします。

近似するために、まずは2次関数を求めます。2次関数にはIllustratorなどのベクターソフトでも使われているベジェ曲線を用います。ベジェ曲線は $ 1,\ 2,\ 3,\ ...,\ n $ 次とありますが、ここでは2次ベジェ曲線を使います。2次ベジェ曲線は始点と終点、そして制御点の3点からなる曲線です。始点と終点は1次関数のときの2点をそのまま使い、制御点は $ (660,\,22) $ とします。制御点を変えることで曲線の曲がり具合を調整できます。

ベジェ曲線の定義より、制御点を $ B_1,\ B_2,\ ...,\ B_{N-1} $ とすると2次ベジェ曲線は、

\begin{align}
P(t) &= \sum_{i=0}^{N-1} B_i\,J_{N-1,i}\,(t)\\
&= \sum_{i=0}^{2} B_i\,J_{2,i}\,(t)\\
&= B_0J_{2,0}(t) + B_1J_{2,1}(t) + B_2J_{2,2}(t)
\end{align}

ここで、$ J_{n,i}\,(t) $ はバーンスタイン基底関数より、

J_{n,i}\,(t) = 
\left(\begin{matrix}
n \\
i
\end{matrix}\right)
t^i (1-t)^{n-i}

よって、求める2次ベジェ曲線は、

\begin{align}
P(t) &= B_0
\left(\begin{matrix}
2 \\
0
\end{matrix}\right)
t^0 (1-t)^2 + B_1
\left(\begin{matrix}
2 \\
1
\end{matrix}\right)
t^1 (1-t)^1 + B_2
\left(\begin{matrix}
2 \\
2
\end{matrix}\right)
t^2 (1-t)^0\\
&= B_0 \cfrac{2!}{0!\,(2-0)!}\, (1-t)^2 + B_1 \cfrac{2!}{1!\,(2-1)!}\, t\,(1-t) + B_2 \cfrac{2!}{2!\,(2-2)!}\, t^2\\
&= B_0\,(1-t)^2 + B_1 2t\,(1-t) + B_2t^2
\end{align}

ただし、$ 0 \leqq t \leqq 1 $ とします。$ t $ の値は曲線上の点の位置を表しており、始点なら $ t = 0 $ 、終点なら $ t = 1 $ です。2次ベジェ曲線の始点を $P_1(x_1,\,y_1) $ 、制御点を $ P_2(x_2,\,y_2) $ 、終点を $ P_3(x_3,\,y_3) $ とすると、

\begin{cases}
  x(t) = (1-t)^2 x_1 + 2t\,(1-t)\,x_2 + t^2x_3 \\
  y(t) = (1-t)^2 y_1 + 2t\,(1-t)\,y_2 + t^2y_3 \\
\end{cases}

次に、始点・制御点・終点の座標を代入します。

\begin{cases}
  x(t) = (1-t)^2\times320 + 2t\,(1-t)\times660 + t^2\times768 \\
  y(t) = (1-t)^2\times20 + 2t\,(1-t)\times22 + t^2\times40 \\
\end{cases}\\
\begin{cases}
  x(t) = -232t^2 + 680t + 320 \\
  y(t) = 16t^2 + 4t + 20
\end{cases}

これで、媒介変数 $ t $ の値によって $ x,\, y $ 座標が求められるようになりました。最後に線形補間で近似します。ここでは、2次関数の区間を3分割します。分割数を増やせば近似の精度が上がりますが、その分メディアクエリも増えるので多くても10分割までにした方が良いです。3分割する場合、$ 0 \leqq t \leqq 1 $ なので、$ t = \frac{1}{3} $ と $ t = \frac{2}{3} $ のときの座標を求めます。

\begin{cases}
  x\left(\cfrac{1}{3}\right) = -232\left(\cfrac{1}{3}\right)^2 + 680\left(\cfrac{1}{3}\right) + 320 = 520.88888... \fallingdotseq 521 \\
  y\left(\cfrac{1}{3}\right) = 16\left(\cfrac{1}{3}\right)^2 + 4\left(\cfrac{1}{3}\right) + 20 = 23.11111... \fallingdotseq 23
\end{cases}\\
\begin{cases}
  x\left(\cfrac{2}{3}\right) = -232\left(\cfrac{2}{3}\right)^2 + 680\left(\cfrac{2}{3}\right) + 320 = 670.22222... \fallingdotseq 670 \\
  y\left(\cfrac{2}{3}\right) = 16\left(\cfrac{2}{3}\right)^2 + 4\left(\cfrac{2}{3}\right) + 20 = 29.77777... \fallingdotseq 30
\end{cases}

これで座標が求められたので、あとは1次関数のときと同様にして各区間の式を求めます。

// ブラウザ幅 < 320pxbody{font-size:20px;}// 320px ≦ ブラウザ幅 < 521px@media(min-width:320px){body{font-size:calc((1/67)*100vw+(1020/67)*1px);}}// 521px ≦ ブラウザ幅 < 670px@media(min-width:521px){body{font-size:calc((7/149)*100vw-(220/149)*1px);}}// 670px ≦ ブラウザ幅 < 768px@media(min-width:670px){body{font-size:calc((5/49)*100vw-(1880/49)*1px);}}// 768px ≦ ブラウザ幅@media(min-width:768px){body{font-size:40px;}}

おわりに

このテクニックを使えば、ブラウザ幅をあまり気にする必要がなくなります。また、今回は font-sizeプロパティを例にしましたが、数値が使えるプロパティなら line-heightmarginpaddingなど何でも使えます。

ちなみに1次関数は、最新のCSSである min()max()関数を使えばより簡略化できます。対応ブラウザはまだ少ないですが...

body{// min([最大値], max([最小値], [aの値]))font-size:min(40px,max(20px,calc((5/112)*100vw)));}

なんとメディアクエリが必要ないのです。さらに最新の clamp()関数を使えばもっと簡略化できます。

body{// clamp([最小値], [aの値], [最大値])font-size:clamp(20px,calc((5/112)*100vw),40px);}

CSSでMath系の関数が使えるようになると表現の幅が広がります。CSS Working Groupによると、sin()cos()sqrt()関数なども使えるようになるとのことでとても楽しみです。

僕は現在、tatamiというSassライブラリを制作中です。フロントエンドエンジニアの方達の労力を少しでも軽減させることと、複雑な処理を @includeするだけで使えるようにすることが目的です。今回紹介した1次関数も_fluid()関数を使えば簡単に実装できます。今後も様々な機能を追加していく予定です。Issueで機能提案してもらえれば、可能な範囲で実装します。

最後に便利な機能を少しだけ紹介して終わります。

機能説明
_data-url()SVGやファイルをBase64エンコード
_aspect-ratio()アスペクト比の固定
_fluid()1次関数を利用したレスポンシブな値
_sticky-footer()スティッキーフッター
_font-face()@font-faceを楽に指定
_readable-color()背景色によって見やすい方の文字色を指定
_media()メディアクエリを楽に指定
_triangle()三角形を描画

背景画像の可変背景のやり方

$
0
0

タイトル通り背景画像background-colorを用いた可変背景のやり方の実装を書いていく.
可変背景とはつまり、ウィンドウを大きくしても小さくしても縦横比が変わらないようになる状態です。

HTMLを以下の様に記述する

<divclass="main"></div>

cssを以下の様に記述する

.main{background-image:url('参照パス');background-size:cover;padding-top:62.75%;}

解説
1.background-size:cover;を必ず指定する
指定しなければ、ブラウザが画像サイズ以上に大きくなった際にリピートしてしまうため。
2.padding-topの指定
値の指定には計算をします。
画像の縦幅÷画像の横幅×100 = %
これらの数値は画像を右クリックで選択し情報を見るから閲覧出来ます。
 例)1004÷1600×100 =62.75%

参照記事↓
background-imageでレスポンシブに対応した可変背景の作り方

Rails6 数値入力時にtypeをnumberにしたのに数値として扱われず困った話

$
0
0

目的

  • 勉強の実施時間を記録するwebアプリ作成の際に数値のinputで詰まり、コミュニティの方に助けていただいた話をまとめる
  • そもそもセオリーを理解できていなかったので二度とこんなことない様にまとめる。
  • .to_iを使って数値に変換できることはなんとなく知識としてあったが定着していなかったのでまとめる。

目標

  • すでにDBに格納されている数値に入力数値を足してDBに格納する。
  • 不動小数点や符号などはとりあえず考えず前述の目標をクリアする。

結論

  • 教えていただいた現役エンジニアさんのお言葉「入力値はtype指定してもStringになってしまうので受け取った側で型を指定して変換する」

問題のコード

  • 下記に問題のコードの一部を抜粋する。

  • コントローラ

    defupdate@post=Post.find_by(id: params[:id])@post.study_time=@post.study_time+params[:study_time]@post.saveredirect_to("/posts/#{@post.id}")end
  • ビュー

    <%=form_tag("/posts/#{@post.id}/update")do%><p>今日つみかさねた時間</p><inputtype="number"name="study_time"><inputtype="submit"value="今日のつみかさね登録"><%end%>

詰まったところまでの概要

  1. 前述の問題のコードにて「今日のつみかさね登録」ボタンを押したところ下記のエラーが出た。

    no implicit conversion of integer into string
    
  2. エラーの内容から足そうとしている数値の型があっていないことがわかった。

  3. 筆者はビューファイルのinputtype="number"を指定して入力型を数値にしようと試みたが同じエラーが出た。

  4. 解決しようと試みたがいろいろ試してくうちに混乱してしまった。

解決方法

  • コントローラで受け取った値の型を数値に変換すことにより問題は解決した。

正常動作したコード

  • 下記に教えていただいた内容を元に修正を行なったコードを記載する。

  • コントローラ

    defupdate@post=Post.find_by(id: params[:id])@post.study_time=@post.study_time+params[:study_time].to_i@post.saveredirect_to("/posts/#{@post.id}")end
  • ビュー

    <%=form_tag("/posts/#{@post.id}/update")do%><p>今日つみかさねた時間</p><!-- type="number"だと0~9までの入力しか受け付けられないためおって修正が必要 --><inputtype="number"name="study_time"><inputtype="submit"value="今日のつみかさね登録"><%end%>

反省

  • .to_iで数値に変換できることは知ってはいたが使いどころが理解できてなかった。
  • そもそもセオリーを理解できていなかった。
  • 今考えると諦めなければ自己解決できたかもしれない。

よかったこと

  • エラー文をコピペで解決することをしなかった。
  • エラー文から問題箇所を特定することができた。

WebでSVGを操作したら意外とハマった

$
0
0

駒場祭のマップページでは、SVGをJavascriptで操作することにより地図機能を実装しています。
しかし、この分野あまり流行ってないからなのか、結構ブラウザによって差異があったりします。ここではその一部を紹介します。

CSS

(Firefox)<defs>にstyleを書かないと<use>にスタイルが適用されない。

SVGには<defs>というHTMLでいう<head>に当たるタグがありそこには、<symbol><style>を置くことが出来ます。
<symbol>は、使い回すパーツを定義することができ、<use>を使って呼び出すことが出来ます。駒場祭のマップでは案内所の記号などに用いています。
さて、このとき、Firefoxだと、<defs>以外にstyleを配置すると<use>にそのスタイルが適用されず、それを用いて色などを設定している場合真っ黒なアイコンになります。

getBBox

これ何

getBBox - Web APIs | MDN
要素のx、y、width、heightを取得できるSVGGraphicsElementの関数です。querySelectorなどで拾ったSVG要素についている関数です。属性から取ればいいじゃんと思うかもしれませんが、<circle>などx、y属性を使わないものでも統一的に取れるので便利です。

(Safari) <use>だとうまく取れない。

<use>要素相手だとgetBBoxは正しい値を返しません。要素名で分岐して素直にx属性などから取りましょう。

(Firefox) display: noneな要素に対し使うとNS_ERROR_FAILUREが発生する

要はdisplay: noneな要素に対しては使えないということです。他のブラウザだと大丈夫なんですけどね。
解決策としてはvisibility: hidden;pointer-event: none;に置き換えるという方法があります。

まとめ

普段からそうですが特にSVGは多くのブラウザで動作確認しましょう。
また何かあったら追記するかもしれません。

次世代CSSがアツい!モダンブラウザのサポート状況は?IE11で見たらどうなるの?調べてみました!

$
0
0

はじめに

この記事はChrome Dev Summit 2019 内のセッション"Next-generation web styling"の視聴レポートです。
Next-generation web styling (Chrome Dev Summit 2019)
※特に注釈がない限り、本稿に掲載の画像は全て上記動画からの引用となります。

また、セッションで紹介されたプロパティのデモは全て、こちらのサイトで見ることができます!
CSS@CDS

冒頭から身も蓋もないことを言いますが、このセッションは本当に面白くて内容もとっつきやすいので、こんな翻訳記事読んでる時間があるならとっとと元動画を見るべきです。
のっけから陽気過ぎるプレゼンター、スライドは最高にキュートでセンスが良く、ちょくちょくデモも挟んでくれるので英語力に自信がなくてもノリでなんとなくの内容は理解出来るはず。
あなたの心に少しでもCSSを愛する気持ちがあるのなら、一刻も早く見るべきです。
いいですか、さあ見ましょう。今すぐ見るのです。

そして見た後で、「面白かったな。ところであそこ何て言ってたかな?」なんて思った時に、この記事が少しでも理解の助けになれば嬉しいです。

Next-generation web styling (Chrome Dev Summit 2019) 1-35 screenshot.png
陽気過ぎるプレゼンターのAdam Argyle氏。このクール過ぎるTシャツどこで買えるんだろ。

Awww scroll-snap

まずは、実はIE11でも使えるscroll-snapから!
ほんのちょっとスクロールするだけで、要素がいい感じの位置にピタッとくっついてくれるというものです。

横方向だけでなく縦方向のスクロールにも対応しており、親にscroll-snap-type: both;overflow: hidden;、子にscroll-snap-align: center;という組み合わせで縦横双方向スクロールも可能です。
Next-generation web styling (Chrome Dev Summit 2019) 2-21 screenshot.png
また、上のキャプチャにあるコードでは、overscroll-behavior: contain;という指定により、親であるコンテナ内を最後までスクロールしてもスクロールイベントが要素の外に飛び出してしまわないようにしています。

ちなみにこのセクションのタイトルは、Chromeがクラッシュした時に出るエラーメッセージ「Aw, snap!」とかけてるっぽいですね、おちゃめ。
image
引用元: Google Chrom ヘルプ

scroll-snap面白いですね、IE11でも使えるのは夢ありますね!なんだか希望が湧いてきました。さあ次いきましょう!
ちなみにこれ以降、IE11で使用可能なプロパティは一切出てきません。

:focus-within

ナビゲーションメニューにありがちな、hoverやfocusで子階層のドロップダウンメニューが出てくるこんなやつ、みなさんも見たことありませんか?こんなコード書いたりしてませんか?
Next-generation web styling (Chrome Dev Summit 2019) 3-31 screenshot.png
これって実はキーボードしか使えないユーザーに非常に優しくないんです。
上記の実装例では、Tabキーでli要素にアクセスした場合に、ドロップダウンメニューが開かないんです。それどころか、さらにTabキーを押すとcssで非表示にしてある子要素にカーソルの照準が当たってしまい、ユーザーは今どこにカーソルがいるのか追えなくなってしまうのです。
これでは到底アクセシブルだとは言えません。

そこで使えるのが:focus-withinプロパティです。
Next-generation web styling (Chrome Dev Summit 2019) 4-6 screenshot.png
これはぜひ!冒頭に貼ったリンクからデモを見てみてください!

@media(prefers-*)

ユーザーの好みに合わせたスタイルを提供するための、新しいメディアクエリだそう。
昨今はデバイス側の設定でフォントの大きさやコントラスト、カラーテーマなんかをユーザーが自由に設定出来るようになっていますが、この設定に合わせてブラウザ側の表現も柔軟に変化出来るというものです!すごい……

例えば、以下のように@media (prefers-reduced-motion)というメディアクエリを書けば、デバイス側の設定で「アニメーションを減らす」としているユーザーに対しては、控えめなアニメーションを提供することが出来るようになります。
Next-generation web styling (Chrome Dev Summit 2019) 5-5 screenshot.png

セッションでは他にも、カラーテーマの切り替えを行う@media (prefers-color-scheme)なんかも紹介されていました。

これだけでもかなりワクワクしますが、なんとまだまだ実装検討中のものが控えているのだとか。
これは楽しみですね〜。
Next-generation web styling (Chrome Dev Summit 2019) 6-25 screenshot.png

Logical properties

続いてCSSの論理プロパティについてのお話です。

これは、要素を従来のようにwidthheightという物理的なアプローチでとらえるのではなく、書字方向(テキストがどっち向きに書かれてるか)によってとらえ直そうとするものです。
Next-generation web styling (Chrome Dev Summit 2019) 7-44 screenshot.png
テキストが伸びていく長さをinline-size、 テキストの行数に相当するものをblock-sizeとして定義し、padding, border, marginにいても、top, left, right, bottomではなく、startendでスタイリング出来るようにしています。

こちらのスライドがとても分かりやすいのですが、要するに論理プロパティを使うと、書字方向によってテキストの先頭位置が違うので、それに合わせて適切な位置に余白をとったり、また縦横比も書字方向の違いによって振り分けたり出来るようになるのです。
Next-generation web styling (Chrome Dev Summit 2019) 8-4 screenshot.png
現時点ではあまりそういうシチュエーションはなさそうですが、論理プロパティでスタイリングをしておけば、書字方向を動的に切り替えた場合にもスタイル崩れが起きないというメリットもあります。
今後多言語対応サイトが増えていくにつれ、重要度が高まっていきそうです。

sticky situations

これは新技術というより、position: sticky;をうまく使ったCSSハック紹介でした。
sticky-desperado.gif
引用: Sticky Desperado / CSS@CDS
こんなアプリっぽい表現をCSSだけで実現できちゃうの、いいですよね〜。
この他にあと2種類のsticky実装例が紹介されており、どれもその工夫具合がたまらないので、こちらもぜひ上記のリンクからデモとコードを見てもらいたいです!

backdrop-filter

Next-generation web styling (Chrome Dev Summit 2019) 12-44 screenshot.png
filterプロパティの親戚みたいな感じですが、こっちは自身の背後にある要素に対して効果をあてられるものです。したがって、backdrop-filterプロパティでスタイリングされる要素は背景が透過でないと、その効果を確認することができません。
valueに入るのは基本的にfilterのvalueと同じものっぽいです。

:is

これはセッション後すぐにマークアップ界隈でめちゃくちゃ話題になりましたね〜!今更感ありますが軽く紹介です。
Next-generation web styling (Chrome Dev Summit 2019) 13-36 screenshot.png
これまでカンマで並べて書くしかなかったスタイリングがこんなにスッキリしました!
カスタムプロパティが出てきた時も思ったんですが、いずれピュアなCSSがどんどんsassのような機能を取り入れていくのでは……

gap for flex-box

まだFirefoxしか対応していないみたいですが、gridレイアウトにおけるgapをなんとflexboxでも使えるんだそう!
Next-generation web styling (Chrome Dev Summit 2019) 14-2 screenshot.png
flexって縦方向の余白調整が面倒だったので、これは嬉しいです!早く他のブラウザにも実装してほしいですね〜。

セッションではgridとflexboxを組み合わせたデモも紹介されていました。
画像の例だと、上がgrid、下がflexboxでスタイリングされているのですが、いずれも単一のgapプロパティにより余白の設定がなされています。これは使い所によってはめちゃくちゃ強そうです。
Next-generation web styling (Chrome Dev Summit 2019) 14-18 screenshot.png

CSS Houdini

CSSフーディーニと読みます。ポケモンのフーディンと同じく、アメリカで一番有名なマジシャンの名前が元ネタのようです。
こいつが一体何なのかについて、とても綺麗にまとめている記事があったので引用します。

ブラウザのレンダリングプロセスの中でJavaScriptがアクセス出来る範囲を広げ(APIの提供)、CSSの機能を拡張出来るようにしようというのがHoudiniです

引用: CSSのHoudiniとは何者か
※ちなみにこの記事には、以下でサラッと紹介するにとどまった3つのAPIについて、もう少し詳しい説明が書いてあります。みなさんぜひ読んでみてください。

Next-generation web styling (Chrome Dev Summit 2019) 16-5 screenshot.png
Houdniだけでいくらでも記事書けちゃいそうなくらいの濃い内容なのでここでは深入りしませんが、jsでポリフィルつけるよりもパフォーマンスが良く、さらにスタイルの拡張性も高いのがHoudiniなのだそう。

ここで現時点でのAPI実装状況について確認できます。
2019年12月現在でまだほとんどのブラウザでサポートされていませんが、Chromeは既に3つのAPIに対応しています。

Property & Values API

CSSのカスタムプロパティにJSでアクセス出来ます。
これによって初期値やフォールバック値、親からスタイルを継承するか否か等をJSで指定できます。
Next-generation web styling (Chrome Dev Summit 2019) 17-54 screenshot.png
さらに、これまでCSSだけでは実現できなかったビジュアルの再現も可能になります。
(この辺は本当に、テキストと静止画での説明じゃ全然ピンとこないと思うので、ぜひ動画をご覧ください)

これを将来的にはCSSだけで全て書けるようにするよ!だそう。すごいなあ……
Next-generation web styling (Chrome Dev Summit 2019) 19-2 screenshot.png

Typed OM API

これまでJSでCSSのスタイル情報を取得しようとした場合、このように文字列が返ってきていました。
Next-generation web styling (Chrome Dev Summit 2019) 20-33 screenshot.png
これを以下のように書き換えて、オブジェクトの形でスタイルのデータを取得するのがTyped OMです。
Next-generation web styling (Chrome Dev Summit 2019) 20-40 screenshot.png

Paint API

Paint Workletと呼ばれるJSを使って、backgroundborderに自由なグラフィックを設定できるというものです。
実際に見てみましょう!
Next-generation web styling (Chrome Dev Summit 2019) 23-2 screenshot.png
paint(rainbowtize)とありますが、このrainbowtizeという描画処理を別途Workletで定義しているというわけです。
Workletとは軽量版のWeb Workerのようなもので、Paint Workletの他にもいくつか種類があります(この記事ではそこまでは触れません)。

Paint Workletを使う利点としては、メインスレッドと別のスレッドでスクリプトが動くので、ページのパフォーマンスに影響を与えないこと!
Next-generation web styling (Chrome Dev Summit 2019) 21-29 screenshot.png

Paint APIについてもっと詳しく知りたい方は、ICSさんのこちらの記事が大変素晴らしいので、ぜひ見てみてください。
どんな背景でも自由に描ける!CSS Paint APIの使い方

おわりに

いかがでしたか?
CSS Houdiniはかなりアツい内容でしたね、こんなに素敵な技術なんだから、きっと標準化も遠い未来の話ではありませんね!

……まあ、真面目に書くと、2016年にHoudini Task Forceで仕様策定が始まってから4年弱で、未だ全てのAPIを網羅するブラウザが存在しないことを考えると、まだまだ標準化までは長い時間が必要だとは思います。それでも、JSでより楽しく自由なマークアップができる未来がいつかくるのだと思うと、今から待ち遠しくってたまりません。マークアップだいすきクラブのみなさんも、ワクワクしちゃったのではないでしょうか。
今回はあんまり触れられなかったけど、いずれCSS Houdiniについて掘り下げた記事も書いてみたいな〜。

あ、ちなみに昨日は同じくChrome Dev Summit 2019のHTMLに関するセッションの記事を書きました!
そっちもぜひどうぞ! HTML will never die but YOU will

電車の発車案内板をHTMLとCSSだけで作ってみる~試行錯誤編その1~

$
0
0

まえがき

この記事は電車の発車案内板をHTMLとCSSだけ作ってみる~実験編~の続きの記事です。

こんにちは。前回は実験ということで、HTMLとCSSだけでドットを組み合わせた電車の発車案内板を作るため実験をしてみましたがしょぼかったので、
まだ途中ではありますが改善点を書きたいと思います。

前回の反省点

・勢いで作ったのでソースコードの解説がなかった
・高速道路みたいなフォントになってしまった
・「川」のはねの部分の再現性がひどい

こういった点が挙げられます。

まずは、改善中のコードのの解説から行きたいと思います

CSS(Scss)

style.scss
$pixel:2px;$pixel2:2px;.guide{width:400px;height:50px;background:#000;&-inner{width:280px;height:40px;padding:5px;display:flex;}&-text-char1{width:40px;height:40px;display:grid;grid-template-columns:1frrepeat(13,$pixel)1fr;grid-template-rows:repeat(18,$pixel2);grid-template-areas:"... ... ... ... ... ... ... ... ... ... ... ... ... ...""... ... ... ... ... ... ... ... ... ... ... ... ... ...""... ... ... ... ... g01 g01 g01 g01 ... ... ... ... ...""... ... ... ... ... g02 ... ... g03 ... ... ... ... ...""... ... ... ... ... g04 ... ... g05 ... ... ... ... ...""... ... ... ... ... g06 ... ... g07 ... ... ... ... ...""... ... ... ... ... g08 ... ... g09 ... ... ... ... ...""... ... ... ... ... g10 g10 g10 g10 ... ... ... ... ...""... ... ... ... ... ... ... ... ... ... ... ... ... ...""... ... ... ... ... ... ... ... ... ... ... ... ... ...""... ... g11 g11 g11 g11 ... ... g12 g12 g12 g12 ... ...""... ... g13 ... ... g14 ... ... g15 ... ... g16 ... ...""... ... g17 ... ... g18 ... ... g19 ... ... g20 ... ...""... ... g21 ... ... g22 ... ... g23 ... ... g24 ... ...""... ... g25 ... ... g26 ... ... g27 ... ... g28 ... ...""... ... g29 g29 g29 g29 ... ... g30 g30 g30 g30 ... ...""... ... ... ... ... ... ... ... ... ... ... ... ... ...""... ... ... ... ... ... ... ... ... ... ... ... ... ...";}@for$ifrom1through30{.char1-guide__dot#{$i}{background-color:#08eb0e;@if$i<10{grid-area:g0#{$i};}@else{grid-area:g#{$i};}}}&-text-char2{width:40px;height:40px;display:grid;grid-template-columns:1frrepeat(12,$pixel)1fr;grid-template-rows:repeat(19,$pixel2);grid-template-areas:"... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...""... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...""... ... ... ... g01 ... ... ... g02 ... ... ... g03 ... ... ...""... ... ... ... g04 ... ... ... g05 ... ... ... g06 ... ... ...""... ... ... ... g07 ... ... ... g08 ... ... ... g09 ... ... ...""... ... ... ... g10 ... ... ... g11 ... ... ... g12 ... ... ...""... ... ... ... g13 ... ... ... g14 ... ... ... g15 ... ... ...""... ... ... ... g16 ... ... ... g17 ... ... ... g18 ... ... ...""... ... ... ... g19 ... ... ... g20 ... ... ... g21 ... ... ...""... ... ... ... g22 ... ... ... g23 ... ... ... g24 ... ... ...""... ... ... ... g25 ... ... ... g26 ... ... ... g27 ... ... ...""... ... ... g28 g28 ... ... ... g29 ... ... ... g30 ... ... ...""... ... ... g31 ... ... ... ... g32 ... ... ... g33 ... ... ...""... ... ... g34 ... ... ... ... g35 ... ... ... g36 ... ... ...""... ... g37 g37 ... ... ... ... g38 ... ... ... g39 ... ... ...""... ... g40 ... ... ... ... ... g41 ... ... ... g42 ... ... ...""... ... g43 ... ... ... ... ... g44 ... ... ... g45 ... ... ...""... ... ... ... ... ... ... ... g46 ... ... ... g47 ... ... ...""... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...";}@for$ifrom1through47{.char2-guide__dot#{$i}{background-color:#08eb0e;@if$i<10{grid-area:g0#{$i};}@else{grid-area:g#{$i};}}}}

この記事を参考に
https://ebifry.jp/css/useless-css-grid

「品」という文字は13×18,「川」いう文字は12×19で作り、
for文で、各g~にgrid-areaを設定していきます。

HTML(ejs)

guidedot.ejs
<html>
    <head>
        <link rel="stylesheet" href="./css/style.css"> 
    </head>
    <body>

        <div class="guide">
            <div class="guide-inner">
                <div class="guide-text-char1">
                    <% pix = 1; %>
                     <% for(i=0; i<=30; i++){ %>
                          <% for(j=1; j<=18; j++){ %>
                          <div class="char1-guide__dot<%= pix %>"></div>
                         <% } 
                         pix++;
                         %>
                    <% } %>
                </div>
                 <div class="guide-text-char2">
                    <% pix = 1; %>
                     <% for(i=0; i<=47; i++){ %>
                          <% for(j=1; j<=19; j++){ %>
                          <div class="char2-guide__dot<%= pix %>"></div>
                         <% } 
                         pix++;
                         %>
                    <% } %>
                </div>
            </div>
        </div>
    </body>
</html>

iには、g~のナンバー分、jには、grid-template-rows:repeat(x,$pixel2);で設定したxの部分の数字が入ります。
pix変数には付与するクラスのナンバーが出力され、jが1増えるごとにインクリメントされる仕組みになっています。

結果と反省点その2

結果

色をJR風に変えてみました。

See the Pen Shinagawa2 by Saito Keita (@saito-keita) on CodePen.

反省点

・明朝体がまだ再現しきれてない
・ドットが荒い

今後の課題

JRの案内板の様に明朝体をドットで再現するにはまだまだ時間がかかりそうですが、
まずは、高速道路のフォントを脱せるように、柔らかいフォントの再現を狙ってみたいと思います。

Viewing all 8541 articles
Browse latest View live