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

OSSのプリザンターをダークテーマにカスタマイズするよ!

$
0
0

ダークテーマってかっこいいですよね~。
最近はスマホはもちろん、Youtubeでもダークテーマ機能が出ており、流行っている感が結構伝わってきます。
主に目への刺激が少ないことから好む方が多いのですが、プリザンターにもダークテーマを実装してほしいという要望がGithubのとあるIssuesから来ていました。

ところでプリザンターってダークテーマ出来るの!?という感じの方もいると思いますが、拡張機能(スタイル)を用いれば出来ちゃうのです。


【プリザンターユーザーマニュアル】スタイル機能


実際に公式ブログでも見た目をカスタマイズした記事がありますのでぜひ興味のある方は見てみるのも良いかもですね!


CSSを使ってプリザンターの見た目を自由にカスタマイズ!


そこで今回は試しに一覧画面のみサクッとダークテーマにしてみましたので共有していこうと思います。
(ホントは全画面に適用したかったけど、思いのほか画面多かったので一覧画面のみでオナシャス!w)

ダークテーマ設定方法

まずは一覧画面右上より「管理」→「テーブルの管理」をクリックします。



「スタイル」タブを選択し、「新規作成」をクリックします。



タイトルに「ダークテーマ」等の任意のタイトルを入れてスタイルに以下のCSSを貼り付けます。

DarkTheme.css
body{background-color:#333333;}.itema{color:white;}.separator{color:white;}#ViewFilters{color:white;}#ViewSelector{background-color:#3333;}.grid-row{background-color:#333333;color:white;}.titlea{color:white;}#ReduceAggregations{color:white;}.data{color:white;}.status-new{color:black;}.grid-title-body>p>pre>span>a{color:white;}.grid-row:hover{background-color:#333333;}table.gridtr:hover{background-color:#333333;}table#Gridtr:hover{background-color:#333333;}.grid-row:hover.grid-title-body{background-color:#333333!important;}.svg-progress-ratetext{fill:white;}.svg-work-value{fill:white;}.field-label{color:white;}.crosstab-rowtd{color:white;}.container-normal{color:white;}.comment{background-color:gray!important;}.comment:hover{background-color:gray!important;}



出力先は「全て」を外して「一覧」にチェックを入れます。
完了したら「追加」をクリックします。



画面下の「更新」ボタンを押すのも忘れずにクリックします。



一覧画面に戻ると・・・良い感じのダークテーマになっていることが分かります!(^^)!


おわりに

ということで!とりあえず流行っているということで今回はプリザンターの一覧画面のみダークテーマにしてみましたがいかがでしたでしょうか??


今後、時間を見つけて画面一つずつダークテーマを適用していこうと思います!


何かカッコいいデザイン等がありましたらぜひ教えてください。
ではでは!また!


【優しく学べる】CSS in console.log

$
0
0

CSS Advent Calendar 2019 12日目の記事になります。

諸注意

  • CSS in console.logはChromeのみ対応となっております。
  • CSS in console.logは今後の業務において使う機会は一切ないかと思いますので、さらっと読み流すことをおすすめします。(実用的な使い方があったら教えてください)
  • 作品だけ見たいよーって人は応用編まで読み飛ばしてください。

なぜ書くか

CSSをconsole.logに適用する記事で、しっかりとまめられた記事ってこの世に存在しないんですよね(するわけがない)
てかドキュメントてきなものすらないんですよ。

このままではconsole.logを華やかにしたいって人が困ってしまいますね。
そんな人を助けたいという思いでこの記事を書くに至りました。

とりあえずやってみる

まずはいつものconsole.log

console.log("We Are CSS");

Screen Shot 2019-12-08 at 8.46.04 PM.png
当然なんの変哲もありません。

スタイルを定義してあげます

consttextStyle="color: teal;";console.log("We Are CSS");

余談ですが、tealはCSSにデフォルトで定義されている色で、「入力のしやすさ」「目への優しさ」「発音のかっこよさ」の全て兼ね備えたCSSカラー界の頂点に君臨する色となっております。
これで普段redblueyellowを背景色に指定して目が痛ぇぇってなっている人に対して一歩差をつけることができますね。

話がそれましたが、定義したスタイルを当てるためにconsole.logを以下のように書き換えます。

consttextStyle="color: teal;";console.log("%cWe Are CSS",textStyle);

Screen Shot 2019-12-08 at 8.42.05 PM.png
するとびっくり、console.logの文字色が変わりましたね。

詳しいことは後ほど説明しますが、
『第二引数にCSSの文字列を渡すと%c以降の文字にスタイルが当たるんだな』
ぐらいに思っておいてください。

入門編

ということでやってまいりましたcss in console.log入門編
誰が入門するんだって話ですが、書きます。

複数のプロパティを使う

先程のスタイルはこうでしたね

consttextStyle="color: teal;";

もし複数定義していくと

consttextStyle="color: teal; font-size: 20px; font-weight: bold;"

見ての通り、この書き方だとプロパティが横に繋がっていってしまうので可読性めちゃ低いです。
ということで、ここでは配列を使って最後に文字列に直してみましょう。
console.logの部分は変わりません。

consttextStyle=["color: teal","font-size: 20px","font-weight: bold",].join(";");console.log("%cWe Are CSS",textStyle);

Screen Shot 2019-12-09 at 5.55.41 PM.png

見慣れた形で書くことができ、出力結果もリッチになってきましたね。
そしてだんだんとjs臭が強くなってきましたね(CSSアドベントカレンダーなのにごめんなさい)

目的の場所にスタイルをあてる

残念ながらconsole.logにはclassやidといった概念は存在しないので普段使っているセレクタとは異なるアプローチが必要となってきます。

百聞は一見にしかず、見てみましょう。

consttealText=["color: teal",].join(";");constplumText=["color: plum",].join(";");constperuText=["color: peru",].join(";");console.log("%cWe %cAre %cCSS",tealText,plumText,peruText);

Screen Shot 2019-12-09 at 5.43.31 PM.png

なんとなくおわかり頂けるかと思います。
つまり、%cから次の%cまでの要素に対して、第二引数から順番に適用されていきます。

おめでとうございます。入門編突破です。

中級編

初級編突破おめでとうございます。
中級編ではconsole.logの落とし穴、デバッグについて触れていきます。

全てのプロパティが使えるわけではない

衝撃的ですね。
使えるプロパティはせいぜい20種類ぐらいじゃないかなと思います。

プロパティが対応しているかどうかは以下で紹介する方法で逐一確認をしましょう。

出力結果のDOMを確認する

実はChromeにはDeveloper ToolsのDeveloper Toolsというものが存在します。
つまり、こういうことですね。

Screen Shot 2019-12-09 at 6.17.43 PM.png

普段見ているDeveloper ToolsもHTML, CSSで作られていることが確認できます。

どうやって見るねんて人はこちらを参考にどうぞ。
How do you inspect the web inspector in Chrome?

先ほどのコードを確認してみると
%cごとにspanで区切られ、スタイルがインラインで展開されています。
デバッグは基本的にここで進めていきます。
Screen Shot 2019-12-09 at 6.32.13 PM.png

先程も言ったとおり、使えるプロパティはせいぜい20種類です。
width, height, displayなどなど...
この世界では様々なプロパティが掻き消されます。

ここでは網羅することができないのでご自分の目でお確かめください。

上級編

ここからは、この制約の多い中で如何にしてアイデアを形にしていくかのtipsを具体的な例を用いて説明していきます。

高さの確保 -> line-height

heightが使えないならline-height
ちなみに、vh使えます。
高さの基準はもちろんDeveloper Toolsになります。

consttextStyle=["line-height: 100vh"].join(";");console.log("%cWe Are CSS",textStyle);

無事、存在感のある出力に成功しました。
Screen Shot 2019-12-09 at 7.23.07 PM.png

中央に寄せたい -> margin

中央寄せの定番であるflex, position, transformといったプロパティは一切通用しません。
また、margin: 0 auto;も機能しません。

ということで、margin-leftで微調整します。
普段のCSSでは絶対にやってはいけませんね。

consttextStyle=["margin-left: 45%",].join(";");console.log("%cWe Are CSS!",textStyle);

いい感じですね。
Screen Shot 2019-12-09 at 7.50.40 PM.png

ちなみに、普段CSSを書いている方なら察しがつくかと思いますが、この書き方、横幅が狭くなると中央寄りではなくなります。

Screen Shot 2019-12-09 at 7.56.43 PM.png

これを避けるためにmargin: 0 45%;にしたらどうなんだということで、試した結果がこちらです。

残念ながら改行が入ってしまいますね。
ちなみに、改行系のプロパティはline-break以外通用しません。
Screen Shot 2019-12-09 at 8.00.01 PM.png

ここでは完璧な中央寄せを見つけることができませんでした。
良い中央寄せの解決策をお持ちの方がいましたら、ぜひ共有よろしくお願いします。

画像を表示 -> background-image

imageタグは使えないのでbackground-imageで対応します。
このへんはいつも通りで大丈夫ですが、強いていうならばpaddingでサイズを確保してあげないといけません。

constimageStyle=["padding: 200px","background-image: url(https://media.giphy.com/media/VbnUQpnihPSIgIXuZv/giphy.gif)","background-repeat: no-repeat"].join(";");console.log("%c ",imageStyle);

Screen Shot 2019-12-11 at 6.27.51 PM.png

ダークモードに対応 -> matchMedia

ごめんなさいめっちゃJSです。
matchMediaを使うとCSSのMedia Queriesの役割が果たせるのでこれでprefers-color-schemeを呼んであげればいいですね。

constisDark=window.matchMedia('(prefers-color-scheme: dark)').matches;consttextStyle=[`color: ${isDark?"white":"black"}`,"font-size: 30px","font-weight: bold",].join(";");console.log("%cCan you read me?",textStyle);

Screen Shot 2019-12-11 at 7.27.58 PM.png
Screen Shot 2019-12-11 at 7.27.05 PM.png

ということで上級編は無駄なtipsを紹介いたしました。
ほかにもこういう裏ワザあるよーって方がいましたらお待ちしております。

応用編

ここからはソースコードを交えつつ作品を紹介していきます。
一応CODEPEN貼っておきますが、CODEPENのページにアクセスしてからconsoleを開かないと見れないので肉眼で確かめたい人のみお使いください(ほとんどの環境でうまく動作する気がしませんが)

ポケモンスライドショー

まずは画像から
最近10年ぶりにポケモンを始めてめちゃくちゃハマってます
みなさんまだ気づいていないようですが、ウッウが恐ろしく強いです。

Dec-11-2019 18-51-55.gif

See the Pen YzPybwb by Kotaro (@mo-ro) on CodePen.

text-shadowアート

次はtext-shadow軸でやっていきます。
おまえ使えるんかい。感がすごい。
ちなみにbox-shadowは使えないです。

text-shadowもちゃんと使えば
こうなります。
Screen Shot 2019-12-10 at 5.53.48 PM.png

See the Pen We Are CSS! by Kotaro (@mo-ro) on CodePen.

もうちょっと頑張れば
こうなりますね。

Screen Shot 2019-12-10 at 5.48.07 PM.png

See the Pen Colorful Bar by Kotaro (@mo-ro) on CodePen.

メリークリスマス

今年もメリークリスマスが近づいてきましたね。
せっかくなので紹介した技術を使ってクリスマス的な何かを表現したいなと思い作りました。

完成
Screen Shot 2019-12-10 at 9.31.17 PM.png

See the Pen wvBGXjK by Kotaro (@mo-ro) on CodePen.

まじできつかった。
この記述量で2日ぐらいかかりました。。。

特にきつかったのが、こいつら強制的にinline-blockになる上にwidthが指定できないのでもちろん全部横並びになるんですよね。
なので\nで改行を挟んで無理やり縦並びにしたところ、(多分)バグで一つ前に定義したスタイルが複製されてしましました。

もしconsole.log芸に取り組む方がいましたら改行を使わない実装を心がけることをおすすめします。

おわりに

こういうことQiitaでやると批判受けそうです怖いんですが、
現在、インターン・就職先大募集中でございます。
console.logを美しくしたいなあって企業がありましたらご連絡お待ちしております。

font-family: serifのみの指定で日本語明朝体が表示されるかチェックする

$
0
0

canvasにsans-serifとsansで「あ」を描画して差異があるかどうかを見るという方法です。

デモ

hasJapSerif
functionhasJapSerif(){constsize=16constcanvas=document.createElement('canvas')constctx=canvas.getContext('2d')canvas.width=sizecanvas.height=sizectx.fillStyle='#000'ctx.textAlign='start'ctx.textBaseline='top'ctx.font=size+'px sans-serif'ctx.fillText('',0,0);constpixels1=ctx.getImageData(0,0,size,size).datactx.clearRect(0,0,size,size)ctx.font=size+'px serif'ctx.fillText('',0,0);constpixels2=ctx.getImageData(0,0,size,size).datafor(leti=0,ii=size*size*4;i<ii;i++){if(pixels1[i]!==pixels2[i]){returntrue}}returnfalse}

これを利用して、Androidなど日本語明朝体がバンドルされてないデバイスのみ、日本語明朝体のウェブフォントを読み込むということができます。

if(!hasJapSerif()){constlink=document.createElement('link')link.rel='stylesheet'link.href='https://fonts.googleapis.com/css?family=Noto+Serif+JP'document.head.appendChild(link)}

去年のAdvent Calendarでシンプルにfont-familyを指定したい記事を書きました。

その記事で全ての主要なデバイスで日本語明朝体を表示する方法の一つに、UserAgentを見てAndroidの場合はGoogleFontsのNotoSerifを読み込むという雑なサンプルコードを紹介しました。

その記事を書いた2018年末、そしてこの2019年末も、主要デバイスで日本語明朝体をバンドルしてないのはAndoridだけですが、この判定方法はもちろんスマートではないですし、今後、Androidで日本語明朝体がバンドルされて font-family: serif の指定だけで日本語明朝体が表示されるようになる可能性もあるので、ちゃんとしたものを投稿しました。

わざわざ日本語明朝体がバンドルされてない場合のみウェブフォントを読み込み適用させる方法をとりたいのは、読み込むリソースの容量をできるだけ小さくしたいだけでなく、ウェブサイトのフォントはどのデバイスでもできるだけ同じにするのではなく、そのデバイスにバンドルされてる標準なフォントをできるだけ使う、という考え方をしてるのもあります。

CSS設計FLOCSS + BEM まとめ

$
0
0

FLOCSSとは

FLOCSS(フロックス)は、OOCSSやSMACSS、BEM、SuitCSSのコンセプトを取り入れた、モジュラーなアプローチのためのCSS構成案です。OOCSSやBEM、SMACSSのいいとこ取りをしたCSS設計思想。

FLOCSS生みの親による基本ルール

命名規則

プレフィックス

layoutならl-Componentならc-のように、属してるフォルダ名の{頭文字}+-でプレフィックスを頭につけ、ファイル名だけでもで判断しやすくする(Foundationはリセットや下地が目的なので除く)

MindBEMding

BEMシステムのシンタックスである、Block、Element、Modifierに分類して構成される規則。

BEM記法におけるElement/Modifierの付け方メモ

JavaScriptで操作され、状態を変化させるためのクラス

プレフィックスにis-をつけ、定義する
この場合、他のObjectへの変化にスタイルを当ててしまうことを防ぐために、is-click自体にスタイルは定義しないこと。
必ず、.c-button.is-clickにスタイルを定義する。

構造

Foundationサイト全体のデフォルトスタイルを管理。
├ reset.scss
├ base.scss
├ variable.scss サイト全体で使える変数
├ mixin サイト全体で使えるmixnを管理
Layout 各ページを構成するサイト全体で共通したエリアを管理。
├ l-header.scss
├ l-main.scss
├ l-footer.scss
Object サイト全体で再利用できるパターンを持つモジュールを管理
Component 小さな単位のモジュールを管理(ボタンなど)
 ├ c-button.scss
 ├ c-grid.scss
 ├ …
Project いくつかの↑Componentと、他の要素によって構成される大きな単位のモジュールを管理
 ├ p-card.scss
 ├ p-profile.scss
 ├ ...
├ Utility ComponentとProjectのモディファイア(パターン)で解決することができないスタイル、また、調整のための便利クラスなどを管理。
 ├ u-utility.scss
 ├ u-color.scss
 ├ u-margin.scss
 ├ u-padding.scss
├ Theme テーマによる色の切り替えなど、ページ単位の色違いとか
 ├ t-blue.scss
 ├ ...

BEMまとめ

BEMは、BlockElementModifierという3つの概念だけ理解してしまえば、あとはclass名の命名ルールに則って記述するだけの単純な方法です。

BEMによるフロントエンドの設計

Block

スクリーンショット 2019-12-12 14.03.17.png

一般的なWebページの場合、Blockは何度も繰り返し出現することが想定できます。そのためBlockを識別するためにはid属性を使わずclass属性を利用します。

Blockはどこにでも置くことができ、Blockの中にBlockを含めることも可能です。ただし、CSSではBlockを入れ子にしてスタイルを指定してはいけません。

Element

ElementはBlockの構成要素で、そのElementが属するBlock内でのみ意味を成します。

Modifier

既存のBlockやElementと似ているけれど、見た目や動きが少しだけ違うものを作りたい場合には、新規にそれらを作るのではなく、Modifierを使うことができます。

例えば、同じリストで、行頭記号が2種類以上存在する場合や、同じメニュー内の「タブ」であっても、現在ユーザーがいるタブだけ、見栄えを変える場合などです。

Modifierは、BlockやElementのバリエーションの軸(例:行頭記号)や、状態(例:現在地)を表すプロパティの役割をします。

Modifierは名前(key)と値(value)を持ち、複数のModifierを同時に使用することができます。

スクリーンショット 2019-12-12 15.14.33.png

この場合のclass名は「Block_key_value」で表します。

次のようなコードの場合、listというclass名のBlockに、typeのバリエーションがあり、それはdiscとcheckという2種類だ、ということがわかります。

index.html
<ulclass="list  list_type_disc"><liclass="list__item"></li><liclass="list__item"></li>
  ...
</ul><ulclass="list  list_type_check"><liclass="list__item"></li><liclass="list__item"></li>
  ...
</ul>

スクリーンショット 2019-12-12 15.24.59.png

index.html
<ulclass="menu"><liclass="menu__item"></li><liclass="menu__item  menu__item_state_current"></li><liclass="menu__item"></li></ul>
BlockとElementの区切り

「Block__Element」と、区切り文字にアンダースコアを2つ繋げたものを使用します。

index.html
<ulclass="menu"><liclass="menu__item"></li><liclass="menu__item"></li></ul>
Modifierの区切りと、Modifierのkeyとvalueの区切り

「Block_key_value」または「Element_key_value」のように、区切り文字にアンダースコア1つを使用します。

index.html
<ulclass="list  list_type_disc"><liclass="list__item"></li><liclass="list__item"></li></ul><ulclass="menu"><liclass="menu__item"></li><liclass="menu__item  menu__item_state_current"></li><liclass="menu__item"></li></ul>
単語の区切り

BlockやElement名を、2つ以上の単語で表す場合は「単語-単語」のように、区切り文字にハイフンを使用します。

index.html
<divclass="search-result"><divclass="search-result__item">...</div></div>

BEM記法におけるElement/Modifierの付け方メモ

参考

リンクに問題ないのに、画像が表示されない(Google Chrome for Mac)

$
0
0

背景

スポンサーのページがあるWebサイトを公開したら、スポンサーのロゴ画像が表示されてないと連絡がきた。

詳細

連絡の内容によると、Mac の Google Chrome でのみ表示されないらしい。(safari や Windowsだと表示される)

しかし、私のPC(Mac)の Google Chrome では表示されている。
→ Chromeのバージョンもしくは、そのPCだけの問題ではないか?

と思い、検証ツールを開いてスクショを撮って送ってもらった。

  • 検証ツール内の画像リンクを確認するが、画像ファイルにはアクセス可能。
  • imgタグのCSSのdisplayプロパティが消されてる。 display: block;になっている。← めちゃくちゃ怪しい

結論

  • 広告ブロックのChrome拡張 (Adblock Plus) が勝手に画像を消していた。
  • WindowsのChromeにAdblockを入れても表示されるが、なぜかMac版だと消される。

スポンサーのロゴを広告と認識したのかな? こればっかりはこっちがどうしようもない……

検証ツールで display: block !important;を上書きすると、取り消し線はなくなったが、表示はされなかった。
もし似たような状態が報告された時は、拡張機能を疑ってかかると良さそう。

対策

CSSクラスに sponsorという文字が入らないようにする。

imgタグに、 .sponsor_logoというスタイルを当てていたが、試しに .sp_logoにすると表示された。

2週間でホームページ vol.失敗編

$
0
0

要点

これからホームページ作るんだ!って人向け

frameset廃止に伴う供養

iframeで憤死

flexboxと言うdisplayはない

ソースコードは供養にて

本題

結論的には1,2週間で1からホームページは割と難しくはない

そもそもHTMLのコードは多分プログラミングと言う括りの中で比較的簡単に入る

勿論CSSとかも

ただし、JavaScriptを使わずに作ろうとはしないでほしい

ほんとにこの一言に尽きる

まぁ、最近の本でJavaScriptを使わないホームページ作成系の本は多分少ないだろうから大丈夫だとは思う

まじでホームページ作成=JavaScriptの学習くらいの気概がいい

あとimportは便利だから覚えておいた方が良いです

たまに書いてない本があるんですけど、import超便利です

CSSを分割できるので、管理が非常にしやすいです

おっと、話を戻しますネ

今の環境でJavaScriptを使わないで作るのは本当に修行と変わらないです

じゃぁ、昔の環境ならJavaScriptを使わないで作るのは苦行じゃなかったの?と聞かれれば

苦行じゃなかったです

そう<frameset>があった頃の環境はネ

多分、JavaScript使って云々って言えば訪問者のカウンター作ったりとか、

そんなことしたい人が学ぶ言語ってイメージが少なからずあったことも理由な気がします

勿論、今でも<frameset>は使えるし、

ズルというか記述を弄ればHTML5とHTML4を混在させることもできるらしい 知らんけどな

とはいえ、HTML5では廃止が決定したんで使い続けても正直……

( ^ω^)・・・(廃止と言うより`<frameset>`が`<iframe>`に統合されるってニュアンス)

この<frameset>がなんで便利かってホームページをパーツに分割して作成できるんですよ

ヘッダー部分だけのHTML、メニュー部分だけのHTML、フッター部分だけのHTMLとかとか

パーツを作成して、それを最後に一枚に統合する

これの利点ってHTML一枚一枚のコードの総量を減らせられるし、変更部分を探して修正するのが楽っていうネ

何より、リンク先をメインコンテンツに指定すればページ全体の読み込みが必要ないから反応が早い(体感かも)

HTML5の環境で同じことは出来はします

<iframe>を利用して似たようにするってやつ

これレスポンシブルにしようとするとですね、JavaScriptを使わないと綺麗にいかないです

今回試してないけれど、もしかするとmarginとかPeddingを利用すれば使わなくて済むかもしれない…

が、おとなしくJavaScriptを勉強しましょう

むしろ使えた方が後々できることが広がるので

まとめると

matome.css
@charset"utf-8";@importurl("importは超重要");@importurl("JavaScriptは必修");



WebアプリケーションってHTML、CSS、JavaScript、なんか言語のちゃんぽんなの?

誰か教えてクレメンス

供養

html

top

top.png

top.html
<!DOCTYPE html><html><head><metacharset="UTF-8"><title>研究生の練習帳</title><linkhref="https://fonts.googleapis.com/css?family=Bitter:400,700"rel="stylesheet"><linkhref="css/style.css"rel="stylesheet"></head><bodyid="top"><header><div><imgsrc="image/logo_shin.png"alt="nixtusi"id="top_pic"></div><divclass="Text"><p>このサイトは練習用に開いたサイトです<br>元や現研究生がわちゃわちゃしているネタ帳です<br></p></div><divclass="Enter"><ahref="index.html"><p>Enter</p></a></div></header><footerid="footer"><p>RDCL@baged</p></footer></body></html>

index

index.png

index.html
<!DOCTYPE html><html><head><metacharset="UTF-8"><title>研究生の練習帳</title><linkhref="https://fonts.googleapis.com/css?family=Bitter:400,700"rel="stylesheet"><linkhref="css/style.css"rel="stylesheet"></head><iframesrc="home.html"name="main"id="main">main_contener</iframe><body><headerid="header"><div><imgsrc="image/logo_shin.png"alt="logo_shin"id="logo"></div><navid="up"><ul><li><ahref="home.html"target="main">Home</a></li><li><ahref="about.html"target="main">About</a></li><li><ahref="mail.html"target="main">Mail</a></li><li><ahref="access.html"target="main">Access</a></li></ul></nav></header><asideid="side"><ulid="right"><br><div><imgsrc="image/member.png"alt="member"id="member"></div><li><ahref="???.html"target="main">???</a></li><li><ahref="???.html"target="main">???</a></li><li><ahref="???.html"target="main">???</a></li><li><ahref="???.html"target="main">???</a></li></ul></aside><footerid="footer"><p>RDCL@baged</p></footer></body></html>

CSS

CSS の総括

style.css
@charset"utf-8";@importurl("head.css");@importurl("main.css");@importurl("foot.css");@importurl("side.css");@importurl("etc.css");

header の部分

head.css
@charset"utf-8";/*headerの大本*/#header{position:absolute;top:0;left:0;width:100%;height:150px;}/*メニュー部分*/#up{text-align:center;}#upul{margin:0%;padding:0%;background-color:black;}ulli{list-style:none;display:inline-block;font-size:140%;width:20%;font-family:'Bitter',serif;}

maincontents の部分

main.css
@charset"utf-8";/*インラインフレームにする*/#main{position:absolute;top:130px;left:230px;width:100%;height:75%;border:1;}

footer の部分

footer.css
@charset"utf-8";/*footerの大本*/#footer{position:absolute;background-color:black;left:0;bottom:0;width:100%;height:35px;text-align:center;font-size:90%;color:white;}

sidemenu の部分

side.css
@charset"utf-8";/*サイドメニューを作成するぞ*/#side{position:absolute;top:160px;left:5px;height:50%;width:200px;border:solid;}#right{display:block;list-style:none;}#rightli{background-color:black;font-size:200%;font-family:'Bitter',serif;height:100%;width:100%;margin:10px;}

その他の設定

etc.css
@charset"utf-8";/*壁紙部分*/body,html{background-color:lightgray;height:100%;margin:0%;padding:0%;overflow:hidden;}/*画像に関する設定*/#top_pic{display:block;margin-left:auto;margin-right:auto;width:80%;height:80%;}#logo{display:block;margin-left:5%;width:345px;height:93px;}#member{display:block;width:109px;height:25px;}/*文字に関する設定*/div.Text{font-size:120%;text-align:center;font-family:'Bittr',serif;}/*Enterの設定*/div.Enter{font-size:400%;text-align:center;font-family:'Bittr',serif;}/*クリックの挙動*/a{color:#3583aa;text-decoration:none;}a:hover{color:#084aa6;text-decoration-line:underline;background-color:whitesmoke;}a:visited{color:#788d98;text-decoration:none;}

後語り

色々な背景とか諸々

始まり

うちの研究室に来る生徒でプログラミングがしたい、

と言うやつの殆どがホームページが作りたいと言い出す件について

自分でやれ、とか、Fortranのプログラミングを学べよ

恥ずかしながら、ホームページなんて高校生の時にちょこっとテンプレートを弄ってたくらいで、

特にアドバイスができず、投げやり気味に、本のコピペでもやったらいいんじゃないと言えば、

何の本をすればいいんですかね、とか飛び出る始末

私が知るか

そんなわけで、死んだ目しながら土台になるホームページの作成を開始した

計画

FC2の無料サーバーを借りて、大まかなレイアウトをして、

そのホームページの一部を各々生徒に担当させるというもの

分かりやすく言うと、メニューバーのリンク先を作らせる、という感じ

三分割フレームで作ればいいだろ(地獄の始まり)

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

$
0
0

100日チャレンジの182日目

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

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

182日目は

【CSS, Rails/Capybara】ラジオボタンのCSS実装で考えたこと(アクセシビリティ、UIテスト)

$
0
0

はじめに

ラジオボタンのデザインについて、CSSをカスタマイズして装飾する際に勉強になったことの共有の記事です。

(注意)記事の中で自動テストの話をしますが、それはRuby on Rails/Rspec/Capybaraを使った場合の話です。それ以外のテストフレームワークは動作を試していません。あらかじめご了承ください。

tl.dr(Too Long, Don't Read)

  • display: none;よりopacity: 0;を使った方が良い
  • display: none;の場合、以下の2点が課題となる
    • キーボードによるボタン操作ができなくなる(アクセシビリティの低下)
    • Capybara(Railsのテストライブラリ)を使ったUIテストにおいて、chooseメソッドでラジオボタンを選択できない

よくあるラジオボタンのCSS装飾

ラジオボタンのデザインはデフォルトのCSSがあるため、上書きをすることが難しいです。そのため、よくあるラジオボタンのCSSの装飾は、以下のように元々のラジオボタンにあたるinputのdisplay: none;で非表示にし、隣接する要素に指定したCSSでcheck/uncheck時の装飾を行うという方法だと思います。これで、独自のデザインをラジオボタンに当てることができるようになります。

ラジオボタンのscss
input{display:none;+span{&:before{/* ラジオボタンの装飾 */}}&:checked+span{&:before{/* ラジオボタンの装飾 */}&:after{/* ラジオボタンの装飾 */}}}
ラジオボタンのHTMLとCSS
<labelfor="gender-man"><inputtype="radio"name="gender"id="gender-man"value="man"></input><span>男性</span></label><labelfor="gender-woman"><inputtype="radio"name="gender"id="gender-woman"value="woman"></input><span>女性</span></label>

display: none;の問題(1) アクセシビリティ

display: none;を使う際のアクセシビリティに関する問題点、および改善方法は、以下の記事にて、非常に分かりやすく記述されています。CSS実装は非常に参考にさせて頂きました。ありがとうございます。
アクセシビリティで気をつけるchecbox,radioのCSS

問題点は端的に言うと、クリックではなく、キーボード操作によるラジオボタンの選択ができなくなるため、アクセシビリティの低下に繋がってしまう点です1。クリック操作ができれば良いかもしれませんが、キーボード操作ができるに越したことはないですし、改善も簡単(display: none; -> opacity: 0;)であるため、display: none;を使わない方が良いと思います。

display: none;の問題(2) Capybaraによるテスト

RailsのUIテストでは、CapybaraというUI操作を簡単に記述できるフレームワークを使っています。例えばラジオボタンのクリックは以下のように簡単に記述することができます。

テスト対象のhtml.erbファイル
<labelfor="gender-man"><inputtype="radio"name="gender"id="gender-man"value="man"></input><span>男性</span></label><labelfor="gender-woman"><inputtype="radio"name="gender"id="gender-woman"value="woman"></input><span>女性</span></label>
# ラベルが女性のラジオボタンがクリックされるchoose"女性"

ただ、このchooseメソッドはdisplay: none;の要素は対象外であるため、クリックすることはできません。これに対する対応策としては、以下のようにfindメソッドでラジオボタンを検索し、clickするという手段が挙げられます。

# NG: `display: none;`の要素はクリックできないchoose"女性"# OK!: `visible: false`で検索すれば要素を見つけることができるfind("#gender-woman",{visible: false}).click

ただ、findメソッドによるクリック方法では可読性が多少下がると感じます。そのため、上述で説明したdisplay: none;を使わない方法(opacity: 0;)を使えば、問題なくchooseメソッドでラジオボタンをクリックすることができます。

# OK: `opacity: 0;`を使ったラジオボタンはクリックすることができる!choose"女性"

最後に

今回は、ラジオボタンのCSS装飾する際に勉強になった、display:none;を使った場合のデメリットと、その改善策について説明しました。

特にアクセシビリティについては、意識して開発をしないと、なかなか身につかないスキルだと思うので、今後も意識してUIデザインに取り組んでいきたいです。

リポジトリ

自分が実装したラジオボタンについては、以下のリポジトリでコードを共有しています。実装はReact.js/TypeScript/styled-componentsです。ちなみに、Ruby/Rsepc/Capybaraのコードはありません汗

https://github.com/Ushinji/ui_components

参考


  1. Google ChromeのWebブラウザにて動作確認(2019/12/12.現在) 


集まれ!擬似要素!

$
0
0

おはこんばんちは。とみぞーです。

今年は擬似要素についての投稿をいたします。
自分の中で迷子になることがあるので、私の中の整理として、投稿させていただきます!

擬似要素ってなんだっけ・・・?

まず、擬似要素とは、htmlの要素の特定の部分に対してスタイル付けをするために使用するものです。

え!

お恥ずかしいながら、この記事を書くにあたり、再度調べていて「知らなかった!」というのがありました。
下記は「擬似クラス」というのですね。
:link:visited:hover:activeや、その他、:nth-child(n):empty:not:enabled:checkedなど・・・

擬似クラスは何なのよ?というと、指定したもの全体に対して影響を与えるもので、
文書構造の範囲外にある情報や単体セレクタで表現できないものを選択するために導入された概念だそうです。
簡単にいうと、とある要素が特定の状態にある時に限定し、適用するセレクタであり、class属性との関連はなしです。
確かに、:checkedとかは文書構造の範囲外ですもんね、、、なるほど、、、!
勉強になりました。
今度は擬似classについて記事を書きます・・・!

主な擬似要素

::first-lineブロックレベル要素の1行目に影響
::first-letterブロックレベル要素の1文字目に影響
::before要素の直前にコンテンツを追加する
::after要素の直後にコンテンツを追加する

ふむふむ・・・

<div class="wrap">
  <p>text1</p>
  <p>text2</p>
  <p>text3</p>
</div>

上記のようなhtmlに、CSSを当ててみます。

.wrap {
  position: relative;
  p {
    &:before {
      content: 'B';
      display: block;
      color: red;
    }
    &:after {
      content: 'A';
      display: block;
      color: blue;
    }
  }
  &:first-line {
    content: '';
    display: block;
    color: pink;
  }
  &:first-letter {
    content: '';
    display: block;
    color: green;
  }
}

結果はこちらになります。
結果画面.png

pタグに設定した ::before::afterにそれぞれ指定した「B」と「A」の文字は常に表示されています。
wrapクラスの :first-line:first-letterのピンクと緑が意図する通りに表示されました。

まとめ

擬似要素と擬似classの違いが、一番個人的に勉強になってしまいました・・・
もっと有意義なことをかけるように努力します!

WebページもOSのDark Modeに対応できる

$
0
0

この記事はニフティグループ Advent Calendar 2019の11日目の記事です。
昨日は @iNakamuraの「自然言語処理でツイートがバズるかを予測しようとした話」でした!
大学時代に、TwitterAPIの制限にぶつかって嘆いていた頃を思い出しました。


はじめに

darkmode_switch.gif
ソースコード: https://codepen.io/rodhamjun/pen/rNaLGLW

さて、今回はWebページもOSのDark Modeと連動できるようになったという話です。
最近、様々なOSが次々とダークモードに対応して、いろんな会社がその対応に追われていますね。
そんな中、ついこの間のChrome Dev Summit 2019の動画を見ていたら、Webサイトでもダークモードに対応できるようになっていた事を知り、やり方もとてもシンプルだったので共有したいと思いました。

ダークモードに対応する

@media(prefers-color-scheme:dark){body{background-color:#000;color:#fff;}}

これだけです。
レスポンシブデザインでおなじみの@mediaメディアクエリを使いますね。
この構文で、OSの設定でダークモードがオンになっている場合は、背景を黒にして、文字を白にします。

prefers-color-schemeで指定できる値は以下の3つです。

  • no-preference
  • dark
  • light

ブラウザ対応状況

現時点では世界人口の76%のブラウザはすでに対応していて、十分普及が進んでいる状況です。
スクリーンショット 2019-12-08 21.26.07.png
https://caniuse.com/#feat=prefers-color-scheme

Chrome Dev Tools でオンオフを切り替える

※ Chrome Canary
chome-dev-tools-dark-mode.gif

Chrome 現行ビルドではまだ、対応していませんが、Chrome Canary (早期試用版) を使えば、開発者用ツールでDark Modeのオンオフを切り替えることができます。
将来的には、通常盤でもこれができるようになる予定です。

・・・More ToolsRenderingprefers-color-scheme

Dark Mode 対応する時に使えるテクニック

JavaScriptでDark Modeがオンかどうか確認する

if(matchMedia('(prefers-color-scheme: dark)').matches){// OS の dark mode がオンになっています}else{// OS の dark mode がオフになっています}

JavaScriptでオンオフを確認するときも、メディアクエリを使います。
既にサイトで Dark Mode のを提供していて、これをOSの設定と連動させるようにしたい場合はこれを使うと良いでしょう。

CSS変数を使う

@media(prefers-color-scheme:light){--background-color:white;--font-color:black;--primary-color:blue;}@media(prefers-color-scheme:dark){--background-color:black;--font-color:white;--primary-color:darkblue;}body{background-color:var(--background-color);color:var(--font-color);}a{color:var(--primary-color);}

light と dark の場合に分けて、同じCSSを2度書くのは管理が大変です。
そんなときに便利なのが、CSS変数です。
ブラウザの対応状況を確認し、合わせて使ってみてください。

画像の彩度を落とす

img{filter:grayscale(30%);}

背景を暗くすると、画像が浮いてしまいます。
これを解決する方法として、grayscaleを下げるとよいそうです。
参考: https://medium.com/dev-channel/re-colorization-for-dark-mode-19e2e17b584b

SVGアイコンを色反転

img[src*=svg]{filter:invert(100%)grayscale(30%);}

黒いsvgアイコンのアイコンは色反転すると、二つ作る必要がありません。

画像を差し替える

<picture><sourcesrcset="night.jpg"media="(prefers-color-scheme: dark)"><imgsrc="day.jpg"></picture>

色反転では対応できないような場合は、
picture タグを使うと、imgタグのsrc画像を差し替えることができます。
参考: https://stackoverflow.com/questions/55787167/how-to-change-image-source-based-on-css-prefers-color-scheme

その他の類似メディアクエリ

今回の、 prefers-color-scheme以外にも、たくさんのアクセシビリティ関連のメディアクエリができました。
アクセシビリティに配慮しているサイトの場合、OSの設定にあわせて、これらで設定のオンオフを切り替えられるようになります。合わせて、確認ください。

  • inverted-colors:色反転の設定
  • prefers-reduced-motion:視差効果を減らす設定
  • prefers-reduced-transparency:透過表現を減らす設定
  • prefers-contrast:コントラストモードの設定
  • forced-colors:強制色指定の設定

最後に

いかがだったでしょうか?

6月の WWDC2019 でiOS 13がダークモードに対応して、会社の先輩が「Webサイトもダークモードに対応しない時代が来るのかな・・・。」と言っていたことを思い出します。

他にも、Chrome Dev Summit 2019の動画はたくさんあります。
Microsoft EdgeがChromium化するのに合わせて、Googleが、Microsoftの人と仲良く発表しているところが印象的でした。
他にも、フォーム要素のデザインがリデザインされ、セレクトボックスでアイコンが使えるようになる話もありました。
近年、Webがますます開発しやすくなって、これからもさらに開発しやすくなる印象を受けました。将来が楽しみです。
気になる方は以下のリンクで、公演の一覧をチェックしてみてください。
https://www.youtube.com/watch?v=F1UP7wRCPH8&list=PLNYkxOF6rcIDA1uGhqy45bqlul0VcvKMr


明日は、@mito1296kのAnsible関係の記事です。お楽しみに!

CSS のカスケードの意味を噛み砕く

$
0
0

MDNとかをみんなで編集!翻訳! Advent Calendar 2019
12/13 分を投下させていただきます。

CSS は Cascading Style Sheetsの略ということは、みなさんご存知のことと思います。
では最初の単語であるカスケード (cascading) の指すところは、おわかりでしょうか。

私は CSS を書くようになってから、かれこれ 10年 以上経ちますが、正直わかっていなかったです。いや、CSS のそういう振る舞いについては初学者に説明できるくらいにはわかってる(はず)のですけど、論理を立てて説明せよと言われたら難しいなというのが実際のところでした。

というわけで、以下のとおり翻訳やってきました。
超〜〜長くて大変でした。1週間くらいかかりました。

原文 (en-US): Cascade and inheritance

日本語訳 (ja): カスケードと継承

まだ少し英語的な文脈なのを、日本語的に直したいなと思いつつも、本日はここまで。
後日もう少し見直しつもりでおりますので、ご指摘ありましたらコメントください。

ページ表示スピードを改善!ちょっとした工夫でできるCSSパフォーマンスの話

$
0
0

この記事は、株式会社エイチームフィナジーAdvent Calendar 2019 13日目です。

インハウスデザイナーで、普段は LPO などをすることが多いです。よろしくお願いします。

CSSパフォーマンスを改善する理由

Google の発表では「3 秒以上を表示に要しているサイトでは 53 % のユーザーが離脱する」
Amazon の発表では「0.1 秒遅くなると、売り上げが 1 % 減少し、1 秒高速化すると 10 % の売上が向上する」と発表しています。
サイトパフォーマンスを向上させることは事業として非常に重要なことの一つと言えます。

パフォーマンス改善のアプローチは多方面色々とありますが、今回は CSS に特化したパフォーマンスの話をさせていただきます。

どんなやり方があるの?

アプローチは大きく分けて 2 軸、ファイル自体の軽量化と、レンダリング時の最適化です。
ブラウザのページ表示の仕組みはものすごくざっくり言うと、ファイルをダウンロードした後内容を解析し、レンダリング処理を行い表示します。
ファイル自体を軽くすること、レンダリングされやすい書き方にすることは画面表示にポジティブな影響があります。
では早速それぞれ紹介していきます!

ファイル自体の軽量化

まずはファイル自体を軽くしてダウンロードを早くするための方法です

ショートハンド(一括指定)で記述

  • 基本的なことではありますが、margin、background などまとめられるプロパティは一括指定で記述しましょう。
    コードもすっきりします。
margin: 10px 20px 10px 20px;

 ↓

margin: 10px 20px;

古いベンダープレフィックスを削除

  • ブラウザ対応をどこまでカバーするのかによりますが、不要なプレフィックスはコード量が増える一因です。
    ファイルの肥大化だけではなくメンテナンス性も下がります、削除&書かないようにしましょう!
    border-radius のプレフィックスをいつまでもつけないようにご注意ください。
  • 必要な場合は、Autoprefixer などで自動付与が良さそうです。
  • Autoprefixer
border-radius:30px;
-webkit-border-radius: 30px;  /* 不要 */
-moz-border-radius: 30px;     /* 不要 */

ファイルの結合& Minify 化

  • 結合は複数にまたがる CSS ファイルを一纏めにしてリクエスト回数を減らします。
  • Minify 化は無駄な空白、コメント、改行などを削除してファイルサイズを軽減させます。
  • オンラインで Minify 化できるサイトもありますが、管理のことを考えて タスクランナーで自動化させることをオススメします。
/* レイアウトCSS */
.hoge_Wrap {
  color: #ffffff;
  background-color: #888888;
}

 ↓

.hoge_Wrap{color:#fff;background-color:#888}

不要なコードを削除

  • 重複や未使用のルールを削除してファイルを軽くしましょう。不要コードを削除することはメンテナンスの向上にも繋がります。
  • chromeの開発ツール
    • 実は開発ツールの More tools > Coverage から使っていないルールを確認することができます。
      赤線が引かれているルールが不要ルールになります。
    • ※サイト全体で使われているものではなく、開いているページ・デバイスでの判定なのでお気をつけください。
      赤線だからといって無闇に削除するとえらいことになります…。

色々できる便利ツール

  • 自分も今回調べて知ったのですが、書いたショートハンドの記述、ファイルの結合&Minify 化、構造像の最適化や不要なコードの削除などができるツールがあるそうです。
  • CSSO、cssnano
    • CSSファイルの構造最適化(似たようなルールを一纏めにするなど) ・ミニファイ・重複コードの削除・空ルールの削除などの機能があり、ファイルを軽くすることができます。
    • CSSO
    • cssnano
  • PurgeCSS
    • CSSファイルからページで未使用のスタイルを検索し、削除したものを新規CSSファイルとして生成するツールになります。
    • UNCSS、DropCSSも同様の機能がありますが、PurgeCSSの方が様々なビルドツールと組み合わせて使うことが可能です。
    • 参考:CSSファイルから未使用のスタイルを削除する方法
    • PurgeCSS

レンダリング時の最適化

次はレンダリングされやすい書き方にするというアプローチです。

セレクタは短くする

  • ブラウザはセレクタの解析を右側(末尾)側からするってご存知でしたか?
    不要なネストはさせない(無駄な検索を抑える)ことでレンダリングが早くなります。
  • セレクタの数を抑えるという点では、BEM はレンダリングが早い書き方と言えます(セレクタのマッチング処理回数が減るため)
div p a {
  color: #008080;
}

こういうコードがあるとまず右側の a を探しに行き、そこから p を検索、その後 div の検索処理に入ります。

.hoge {
  color: #008080;
}

この場合は上記のように class を設定した方がレンダリングスピードはアップします。

CSS をインライン化

  • 別途CSSをダウンロードする必要がないので、HTMLファイル内にインラインで記述することがレンダリングとしては一番早いです。(もちろん管理上どうなのか、という問題はあります。)
  • 1 枚ものの LP であれば選択肢としてありですね。

FV の CSS のみインライン化

  • CCSS(Critical CSS)という、ファーストビューの CSS のみインラインで記述、使わない CSS は遅延読み込みといった対応をすることで表示を高速化させるという方法があります。
  • ツールもあるようです。
    Critical Path CSS Generator
    改善したいページのURLを入力し、「Generate」ボタンをクリックすることでコードが生成されます。

最後に

  • 書くだけだならばどうとでも書くことはできますが、上記のことを頭に入れてパフォーマンスを意識した CSS の書き方ができるとより良いです◎
  • それでは皆さま、良いマークアップライフを:open_hands:

ターミナルに雪を降らせる

$
0
0

LIFULLその2 Advent Calendar 2019の13日目です。
去年も13日目だった気がする。しかも今年は13日の金曜日。

すっかり冬になりました。
冬といえば雪
どうせなら雪を見ながら作業したいなーなんて思いました。
というわけで

雪を降らせる(ターミナルに)

使うもの

雪を降らせるための作戦

HyperはUIコンポーネントが以下のようになっています。
公式より、コンポーネントについて
Termのコンポーネントに雪を降らせるための要素を重ねて表示させることにします

とりあえず、ローカルのプラグインを読み込ませる

Macの場合は、~/.hyper_plugins/local/以下にプラグインを自作して、読み込ませます

mkdir ~/.hyper_plugins/local/snow
touch ~/.hyper_plugins/local/snow/index.js

設定ファイルを編集して、ローカルのプラグインを読み込むようにする

~/.hyper.js
localPlugins:["snow"],

ローカルプラグインの準備ができたので、あとは雪を降らせるためにいじるだけです

まずは雪を降らせる場所作り

作成したindex.jsで雪を降らせる場所(div)を追加します

index.js
exports.decorateTerm=(Term,{React,notify})=>{returnclassextendsReact.Component{render(){returnReact.createElement('div',{style:{width:'100%',height:'100%',position:'relative'}},[React.createElement('div',{class:'snowfall'}),//雪を降らせるためのdiv要素React.createElement(Term,this.props),//元々のターミナル]);}}}

細かい説明は省きますが、元々のTermコンポーネントに雪を表示するための要素を追加しています。
詳細については、このあたりが参考になります。

index.jsを変更したら、⇧⌘Rでリロードしてください。

実際に降らせる雪づくり

雪を降らせる場所に、雪の要素を追加します。

index.js
exports.decorateTerm=(Term,{React,notify})=>{returnclassextendsReact.Component{render(){returnReact.createElement('div',{style:{width:'100%',height:'100%',position:'relative'}},[React.createElement('div',{class:'snowfall'},React.createElement('div',{class:'snow'},'')),React.createElement(Term,this.props),]);}}}

誰がどう見ても、雪が追加されました。
スクリーンショット 2019-12-12 2.25.05.png

雪を降らせる

スタイルを追加して、雪を降らせるアニメーションやら表示位置やらを調整します。
特に凝ったことはしないので、アニメーションもcssで完結させます。

index.js
exports.decorateTerm=(Term,{React,notify})=>{returnclassextendsReact.Component{render(){returnReact.createElement('div',{style:{width:'100%',height:'100%',position:'relative'}},[React.createElement('div',{class:'snowfall'},React.createElement('div',{class:'snow'},'')),React.createElement('style',{},`
          .snowfall {
            position: absolute;
            height: 100%;
            width: 100%;
            pointer-events: none;
            z-index: 100;
          }

          div.snow {
            animation: snowfall 3s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 10%;
          }

          @keyframes snowfall {
            0% {
              transform: translateY(0) rotateY(0);
            }
            50% {
              transform: translateY(50%) rotateY(180deg);
            }
            100% {
              transform: translateY(100%) rotateY(360deg);
              opacity: 0;
            }
          }
        `),React.createElement(Term,this.props),]);}}}

<style>の要素を直接追加して、cssを当てるようにしています。
単純なのでとりあえずこれで良いかなと

自分なりのポイントを解説すると、z-index: 100;の部分がポイントで、
開発者コンソールで確認すると、元々のTerm要素にz-indexが設定されているようで、
問答無用で最前面に出すために100とかの数値を設定してます。
最前面に出すためなので、値は100でも1000でも10000でも問題ないです。

とりあえずここまでで雪が降り始めました。
snowfall#1.gif

雪をふやす

あとは適当に雪を追加して、アニメーションの時間などをいじって雪っぽさを演出します。

長いので省略
index.js
exports.decorateTerm=(Term,{React,notify})=>{returnclassextendsReact.Component{render(){returnReact.createElement('div',{style:{width:'100%',height:'100%',position:'relative'}},[React.createElement('div',{class:'snowfall'},React.createElement('div',{class:'snow'},''),React.createElement('div',{class:'snow2'},''),React.createElement('div',{class:'snow3'},''),React.createElement('div',{class:'snow4'},''),React.createElement('div',{class:'snow5'},''),React.createElement('div',{class:'snow6'},''),React.createElement('div',{class:'snow7'},''),React.createElement('div',{class:'snow8'},''),React.createElement('div',{class:'snow9'},''),),React.createElement('style',{},`
          .snowfall {
            position: absolute;
            height: 100%;
            width: 100%;
            pointer-events: none;
            z-index: 100;
          }

          div.snow {
            animation: snowfall 3s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 10%;
          }

          div.snow2 {
            animation: snowfall 8s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 20%;
          }

          div.snow3 {
            animation: snowfall 2s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 30%;
          }

          div.snow4 {
            animation: snowfall 5s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 40%;
          }

          div.snow5 {
            animation: snowfall 10s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 50%;
          }

          div.snow6 {
            animation: snowfall 7s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 60%;
          }

          div.snow7 {
            animation: snowfall 9s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 70%;
          }

          div.snow8 {
            animation: snowfall 4s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 80%;
          }

          div.snow9 {
            animation: snowfall 2s linear 0s infinite normal;
            position: absolute;
            height: 100%;
            left: 90%;
          }

          @keyframes snowfall {
            0% {
              transform: translateY(0) rotateY(0);
            }
            50% {
              transform: translateY(50%) rotateY(180deg);
            }
            100% {
              transform: translateY(100%) rotateY(360deg);
              opacity: 0;
            }
          }
        `),React.createElement(Term,this.props),]);}}}

完成したやつ && 作業風景

snowfall#2.gif

まとめ

ターミナルに雪を降らせたけど、予想以上に鬱陶しいので、
雪が見たければ本物の雪を見にいこう

参考

日本語Webフォントをサブセット化してCSSで使用する

$
0
0

(前日だけ空いてしましましたが)パーソンリンクアドベントカレンダー、折り返し地点を超えた13日目の投稿です。
今回はwebサイトでのカスタムフォントのサブセット化について書きます。

フォントのサブセット化とは

フォントを特定の文字のデータだけ抽出したフォント(サブセット)に分割する事をサブセット化と呼んでいます。
たとえば、英文字しか使ってないページでは、英数字のサブセットフォントのみ使用する、といった事が考えられます。
最小限のサブセットのみ使うようにすれば、ページ表示時間短縮や通信データ量の短縮が期待できます。

Googleによる詳細な解説
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization

サブセット化のパターン

サブセットの分け方としてはおおよそ以下の3つが考えられます

  1. 英数字、記号、かな・カタカナ、第1水準漢字、第2準漢字といった文字としての意味をもったサブセット
    英字はいいけど、漢字の容量が大きいのは変わらない・・・

  2. サイト内で実際に使用している文字のみを持つサブセット
    使用する文字が決まっている、すなわちテキスト部分が静的なサイト向け。

  3. 出現頻度や同時に出現する確率で分けたサブセット
    動的コンテンツのサイトで特に有効。
    すべての文字をカバーしつつ、ページごとに最小限のフォントファイルの読み込みを行おうとします。

実際にやってみる

今回は3の方法でサブセットを作成するために、簡単なスクリプトを用意してみました。
font-google-subset
以下、スクリプトの内容と実行手順です。

フォントのサブセット範囲を決める

Google FontsのNoto Fontのcssを見ると、unicode-rangeを使って読み込むサブセットを細かく指定しています。
どういうアルゴリズムで算出した分け方なのかは公開されていないようですが、恐らく使用頻度や文字の種類、漢字の部首グループなどで分けれているのだと思います。
今回はこのunicode-rangeの分け方を拝借します。
https://fonts.googleapis.com/css?directory=3&family=Noto+Sans+JP
Google FontsのCSS

フォントのサブセットを作成

font-rangerを使い、全パターン分のサブセット作成と、サブセットに対応した@font-faceのリストを持つCSSファイルの生成を行います。

サブセット化したフォントを読み込むCSSを作成

font-rangerでサブセットと同時に出力されたCSSを1つのファイルに統合して、Google FontsのCSSと同様のものを作成します。

あとは作成したCSSとサブセットフォントをサイトに配置するだけで、各ページで必要に応じたサブセットをブラウザが読み込んでくれます。

なお、@font-faceは古いブラウザだと対応していませんので、そういう環境でもフォントを使いたい場合はfallbackとしてttf/woffを用意する必要があります。

実際に実行してみる

以上の手順を実行する簡単なスクリプトを用意してみました。
font-google-subset(実行手順はREADME.md参照 / 一部ttfなどは動かないようです)

なお、実際にサイトで使用する際は使用するフォントの利用規約に注意してください。
フォントのサブセット化は、各フォントの規約における改変にあたる可能性があります。

参考にさせていただいた記事

日本語 Web フォントの読込み速度を改善する - その1


以上となります。明日は@shothymさんの記事ですね。お楽しみに!

2019年 スマホブラウザ対応で苦戦したこと

$
0
0

私は普段業務で、Webページの保守・運用を主にしております。
特にスマホブラウザメインのサイトを扱っているため、スマホでの表示崩れや仕様に対応しなければならないことが多いです。

そのなかでも、今年1年の間で直すのにてこずったスマートフォン向けの対応について、今回は備忘録もかねて紹介してみようと思います。

1. iOS編

1-1. 横画面表示に切り替えると、文字の大きさがバラバラになる

文字サイズがバラバラになってしまったコード

まずは、実際に横画面にして崩れてしまっていた箇所を、最小限のコード量で再現してみます。

<pclass="line-height-big">てすと</p><pclass="line-height-big">てすてす<spanclass="red">てすと</span></p><style>*{line-height:1;}.line-height-big{line-height:1.2;}.red{color:#ff0000;}</style>
  • まずすべての要素(*セレクタ)に line-height:1を指定。
  • 異なる値のline-heightを指定したクラス(今回は.line-height-big)を作成。
  • pタグを2つ用意し、片方に.line-height-bigを指定
  • .line-height-bigで囲った要素の子要素にただのテキストとspanで囲ったテキストを配置

スクリーンショット 2019-12-09 11.47.07.png
スクリーンショット 2019-12-09 13.41.58.png

横画面表示にすると、なぜか.line-height-bigの中のspanの中の文字だけ小さくなってしまいました。
ちなみにclass="red"はみやすくするためにつけたので、文字を赤くしなくても同じことが起こります。

原因

ブラウザを横画面にした時に、文字サイズを調整する機能がうまく動作せずにサイズがバラバラになってしまいます。
下記のコードのように-webkit-text-size-adjust: 100%;を指定すれば、横画面にしても文字サイズが変わらず、大きさがバラバラになることもありません。

body{-webkit-text-size-adjust:100%;}

スクリーンショット 2019-12-09 13.16.09.png
スクリーンショット 2019-12-09 13.16.26.png

だけど、横画面にした時、文字が大きくなってほしい

しかし今回は、横画面にした時に文字サイズが大きくなって欲しかったため、-webkit-text-size-adjust: 100%;は使わずに対応するために挙動について検証してみました。

 パターン1
<pclass="line-height-big">てすと</p><pclass="line-height-big">てすてす<spanclass="red">てすと</span></p><style>*{line-height:1;}.line-height-big{line-height:1.2;}.red{color:#ff0000;}</style>

スクリーンショット 2019-12-09 13.55.20.png
line-heightの値が異なる要素だけ小さくなってしまっているようでした。

 パターン2
<p>てすと</p><pclass="line-height-big">てすてす<spanclass="red">てすと</span></p><style>*{line-height:1;}.line-height-big{line-height:1.2;}.red{color:#ff0000;}</style>

スクリーンショット 2019-12-09 13.46.06.png
この場合も同様、文字が小さくなってしまっている箇所はline-heightの値が他と異なっています。

解決方法

ということで、line-heightの値が一定になるように修正します。

<pclass="line-height-big">てすと</p><pclass="line-height-big">てすてす<spanclass="red line-height-big">てすと</span></p><style>*{line-height:1;}.line-height-big{line-height:1.2;}.red{color:#ff0000;}</style>

上記のコードのようにline-heightの値を揃えれば、文字の大きさが一定になりました。

スクリーンショット 2019-12-09 11.58.54.png

でも、下記のようにpタグが1つだけの場合だと

<pclass="line-height-big">てすてす<spanclass="red">てすと</span></p><style>*{line-height:1;}.line-height-big{line-height:1.2;}.red{color:#ff0000;}</style>

スクリーンショット 2019-12-09 14.44.39.png

line-heightの値が異なるものが混じっていますが、文字サイズはバラバラになりません。

line-heightの値が異なる要素が3つ以上ある場合、バラバラになってしまう?ように思えますが
どの文字が小さくなってしまうのかなどは、規則性がわからずじまいでした、、、

しかし今回のように、同じブロックの中に、さまざまなline-heightが混在しないようにすれば、他の原因で文字サイズがバラバラになってしまう事象には遭遇していません。

詳しい仕様などがわかる方がもしいらっしゃれば、コメントでぜひ教えていただけると助かります😿

1-2. 入力フォームにカーソルを合わせたときにズームしないでほしい

iOS端末では、input要素のフォントサイズが16px以下だと、入力フォームびカーソルを合わせたときに拡大表示される機能があります。

textarea{font-size:10px;width:60%;height:50px;margin:020%;padding:10px;resize:none;}

font-sizeを16px以上にすれば拡大されないようになります。

textarea{font-size:16px;width:60%;height:50px;margin:020%;padding:10px;resize:none;}

font-size 16px以下で、拡大しないように実装したい場合は、scaleを利用します。

textarea{/* scale(0.5)で半分の大きさになってしまうので、全て2倍の値にする */font-size:20px;width:120%;height:100px;margin:040%;padding:20px;resize:none;transform:scale(.5);transform-origin:lefttop;}

scaleによって文字以外も縮小されてしまい、見た目が少し変わってしまうので、縮小率に合わせて大きい値を指定するか、入力フォームをdivなどで括って、そこにcssを当てるなどで対応できると思います。

こちらの方法使用する場合は、標準の機能を動作させないようにすることになるため、フォントサイズが小さくても操作性に問題がないか、要検証です😓

2. Android編

2-1. Android4以下の一部ブラウザでFlexが崩れる

これは単純にブラウザが対応していないだけでした😅
ベンダープレフィックス付与すれば、Android4以下でもFlexを使用できます。

Flexコンテナ

.flex{display:-webkit-box;/* Android用 */display:flex;}

Flexカラム

.flx-column{-webkit-box-flex:1;/* Android用 */flex:110;}

justify-contentプロパティ

.flex-start{-webkit-box-pack:start;/* Android用 */justify-content:flex-start;}.flex-end{-webkit-box-pack:end;/* Android用 */justify-content:flex-end;}.flex-center{-webkit-box-pack:center;/* Android用 */justify-content:center;}.flex-space-between{-webkit-box-pack:justify;/* Android用 */justify-content:space-between;}

align-itemsプロパティ

.flex-start{-webkit-box-align:start;/* Android用 */align-items:flex-start;}.flex-end{-webkit-box-align:end;/* Android用 */align-items:flex-end;}.flex-center{-webkit-box-align:center;/* Android用 */align-items:flex-center;}.flex-baseline{-webkit-box-align:baseline;/* Android用 */align-items:baseline;}.flex-stretch{-webkit-box-align:stretch;/* Android用 */align-items:stretch;}

align-contentは使えません、、、😔

制作のときは、開発者ツールを使ってAndroid用のベンダープレフィックスが付いているcssのみを有効にして表示確認をすれば、Flexが未対応の実機でも崩れず表示できました。

まとめ

以上、対応に手こずったスマホブラウザ対応についてまとめてみました。
同様の現象で困っている人のヒントになれば幸いです。。。🙇‍♂️


Rails JQuery 動かない

$
0
0

JQueryはちゃんと書けている。ソースも更新されている。

しかし、狙い通りに動作しない。Javascriptのエラーもでてない。
単純にalert();とかconsole.log();とかやっても反応しない。

全く動かないわけではなく、ページを再読み込みしたときは狙い通りに動く。
ぐぬぬ。

理由はturbolinksだった。

application.html.erb
<%=javascript_pack_tag'application','data-turbolinks-track':'reload'%>

turbolinksがあるとSPAのような動きをするらしい。(SPAよく知らないが)

Rails 4のturbolinksについて最低でも知っておきたい事
turbolinksの動作は、すごく大雑把に言うと以下の通りです。

  1. リンクのclickイベントをフック
  2. リンク先のページをXHRで取り寄せる
  3. レスポンスをDOM化
  4. 現在のページと取り寄せたページの外部JavaScriptファイルとCSSファイルが同一なら、titleとbodyを読み込んだページのもので置き換える

上記の理由で$(document).readyが発火しない。なるほど。

Rails5では書き方がまた違う

Rails5でjqueryを動かす方法

動いた。

変更前.js
$(function(){// 処理});
変更後.js
$(document).on('turbolinks:load',function(){// 処理});

flexアイテムの中でellipsisが効かない件

$
0
0

タイトル通りですがコードペンにあげたので見てください(Bootstrapを使ってますので知らない人は分かりづらいかもしれません)。

https://codepen.io/masamoto-miyata/pen/RwNRedO

フレックスアイテムの中にdivをおいてそこにellipsisを書いても効きません。親のフレックスアイテムにoverflow: hidden;をかける必要があります。かけないと中のdivがまったく縮まないではみ出ます。ちなみにoverflow: auto;でも大丈夫でした。

しかも、中のdivがinline-blockだと、はみ出はしませんが...になりません。blockである必要があります。

Chrome、FireFox、Safariで確認したのでバグではないでしょう。どういう理屈でこうなるのか分かりません。ご存じの方いらっしゃいましたら教えていただけるとうれしいです。

追記(2019/12/13 12:24)

min-width問題を忘れていた。flexアイテムはmin-widthがautoになるんでしたね。コードペンの方を編集しましたが、overflow: hidden;の代わりにmin-width: 0;でもいけました。ただ、中のdivがinline-blockだとmin-width: 0;でも縮まないですね。うーん。多分細かい仕様を聞けば納得いきそうな話ではありますが、ややこしいですね。

BEMとコンポーネントとCSSの組み合わせで失敗した話

$
0
0

はじめに

はじめまして!:boy_tone1::boy_tone1:
初めて投稿します、じいやと申します。:older_man_tone1:

最近、WebアプリのUIリニューアルに際して今までのCSSを全て消して、新しいCSSを書くというタスクを担当しました。別のプロジェクトでBEMを一瞬使っていたので、今回もBEMを使ってやってみようと思って進めていきました。

その中で、問題、そして葛藤があったのでそれを書いていこうと思います。

背景

普段BEMを書くとするとCSSではなくSassと使用すると思うのですが、今回は背景もありCSSでやることになりました。

思えば、ここでSassを使わないならBEMを使う旨味が薄くなってしまうので冷静になってBEMではないものを考慮するべき、もしくはSassを使うように考えるべきだったのかもしれません。:frowning2:

BEMとは

BEMを知らない方のために軽く説明すると、BEMとは
- Block
- Element
- Modifier
の頭文字をとったもので、CSSの設計手法です。

BEMではHTMlの要素を細かく分解して、コンポーネントごとにしていきます。
Blockは親コンポーネント、Elementは子コンポーネントを指します。
Modifierはその要素の特徴を装飾するトッピングのような物です。

これだけだと何を言っているかわからないですよね笑:sweat_smile:
例をあげて説明します。

例えば、フォームを作るとします。
HTMLはこんな感じに

index.html
<form><label>Email</label><inputtype="email"name="email"/><label>Name</label><inputtype="text"name="name"/><inputtype="submit"value="Submit"/><inputtype="reset"value="Reset"/></form>

ここにBEMを入れるとすると、まず大きなBlockとしてformがあります。
ですのでとりあえず適当に

main.css
.form{max-width:85%;margin:24px0;padding:24px;}

とします。
次に、formの中にあるものを見ると<label><input>ですね。(厳密に言えば<input>に入力欄とボタンがあります。)これらは、formというBlock内のElementになります。

BlockElementはアンダースコア2つで繋ぎます。
ですので、下記みたいにします。:writing_hand:

main.css
.form{max-width:85%;margin:24px0;padding:24px;}.form__label{display:block;font-size:1.2rem;margin-bottom:12px;}.form__input[type=text],.form__input[type=email]{display:block;width:100%;height:28px;border-radius:5px;margin-bottom:12px;}.form__button{display:block;background-color:#03fc90;width:80px;height:36px;border-radius:5px;margin-bottom:12px;}

いい感じです。
最後に、Modifierです。これは、要素を修飾するものです。今回はリセットボタンをグレーにしましょう。(これに関してはいくつか書き方があると思いますが、CSSを使っていて.form_buttonのcssを継承したいので下記のようにしました。)

main.css
~~.form__button{display:block;background-color:#03fc90;width:80px;height:36px;border-radius:5px;margin-bottom:12px;}.form__button.--gray{background-color:#d9d9d9;}

クラスをそれぞれのタグにつけたのが以下です。

See the Pen yLyJGEd by RyojiK74 (@ryojik74) on CodePen.

とてもCSSが整っていて、わかりやすいですよね:sunny::sunny:
CSSを見ただけでなんとなくどこに使われているかがわかります。

問題はここからだぁ!!:fist::fist:

急にテンションが高くなりましたが、ここから複雑になってきたのです。
まず僕たちは、デザイナーから受け取ったデザインを見てみました。するとそこには、同じスタイルをもつコンポーネントが多くありました。まあとりあえずページを作ってみて、共通化できるところはしていこうということで進めていきました。:scissors:
1ページ目(使い回し)

See the Pen yLyJGEd by RyojiK74 (@ryojik74) on CodePen.

次のページを見ると同じボタンが今度は<form>内ではなく、リンクとして使われていました。
とりあえずさっきのクラスを使いまわそうとしました。
2ページ目

See the Pen another_page by RyojiK74 (@ryojik74) on CodePen.

見た目は悪くない...だけど、これHTMLをよく見るとわかると思いますが、contactというブロックなのにform__buttonが存在してしまっている...。うーん、ビミョい...。:sweat:

でも、ボタンのスタイルを一括で変えたいというタイミングがこれ以降であるかもしれないことを考えると同じスタイルだが別の名前を持つ物を作るのは避けたい...。
泣く泣く、ボタンコンポーネントは例外として、.content-buttonというクラスを作ってしまいました。:robot:
いや、これSassだったら@extendつかってもっとスマートにbutton継承しながらかけるのに...。

なんやかんや、.content-buttonのおかげで一応作業を進められるようになった我々を待ち構えていたのはmargin-bottom君でした。

レイアウトとコンポーネントの狭間

次のページでも、同じボタンが使われていましたが 一つ違いがありました。それは、彼だけmargin-bottom: 36px;だったのです。
今まで、12pxだったから甘えてきたものの3倍の36pxはきついものがありました。
というかそもそもコンポーネントで設計する場合はmarginなどのレイアウトに関わる部分はつけるべきではありません。つけてしまうと、このように再利用性が著しく下がってしまいます。

正直詰みの状態でした。:frowning2::frowning2:
BEMの見やすさやメンテナンス性を保持しようと考えると--mb-24みたいな汎用クラスを作成はしたくないですし、かと言ってCSSのメンテナンス性を踏まえるとクラスを分けたりしたくはありません。最終的に僕らはプロジェクトのエンジニアリーダーに話しをして、タグに直接styleを埋め込むもしくはページのheadにstyleを埋め込み、そこで各ページに必要なmarginなどを書くことでとりあえず落ち着きました。:gear:

まとめると問題はなんだったのか??

Sassの@extendがないCSSでメンテナンス性とBEMの両立をしようとしたのが無謀だったのだと思います。
使うフレームワークによるとは思いますが、BEMを使い、さらにコンポーネントを作ってそのメンテナンス性をあげる場合はSassを使わない手はないと思います。

もっと設計の段階でいろいろ見越して考えるべきだったと後悔しています。:sob:

僕とは違いみなさんは先のことをきちんと考えてから導入されているかもしれませんが、これからBEMを考えてみようと思う方に届けばいいなと思います。

ここまで読んでくださりありがとうございました:older_man_tone1:

連番を含むコードの作成をちょっとだけ楽にするツールを作る。

$
0
0

はじめに

今回は、趣味としてちびちびスキルアップしてきたプログラミングで、何か作ってみようと考えた末に作った、自分用のツールです。
やはり形になるものを1つ作ると、考案から完成までの流れが理解しやすくなるなぁと思いました。

これまで、バッチファイルから始めて、HTML/CSS/JavaScript/Pythonを触ってきましたが、今回はHTML/CSS/JavaScriptを使いました。とりあえず、作ったものと参考にしたURLとかを備忘録的に書いておこうかと思います。

きっかけ

  • 趣味としてかじっていたプログラミングを使って何か作りたかった
  • 連番が出てくるコードはたくさんあるが、for文やEmmetのような便利なツールを使えない/使いたくない状況で、いちいちコピペして数字を打つのが面倒だと感じた場面が最近あった

目標とするもの

例えば、

example.css
bodyinput[num="1"]>span#index_1bodyinput[num="2"]>span#index_2bodyinput[num="3"]>span#index_3bodyinput[num="4"]>span#index_4bodyinput[num="5"]>span#index_5

こういうのを作るのを楽にしたい。

プラン立て・HTML/CSSで骨組み作り

プランを立てる大切さ

完成形のイメージを持って開発を行うことはとても大切。今回はHTML/CSS/JavaScriptを使用したが、しっかりとしたプランを立てておくことで、ID名やクラス名、属性名を分かりやすいものにし、その後のメンテナンスもしやすくなるようにできる。

今回のプラン

[共通の文字列]{連番}[共通の文字列]{連番}・・・のような構造になっているので、それにあわせて設計する。

[文字列]{連番}[文字列]という形を基本として、必要な分だけ[文字列]{連番}の組み合わせを追加できるようにする。

骨組みの作り上げ

完成体の体が見えてきたため、HTML/CSSを書き上げる。基本的にすべてのパーツをJavaScriptでの処理に使用するので、ID名などは分かりやすいものをつけることを心がけた。

参考 : CSS クラス名リスト
ID/クラス名の名付け方がとても参考になる。

また、フリーのアイコン素材を配布しているサイトはたくさんあるので、とりあえず探せば見つかる。(今回はHTMLファイルに埋め込んだ)

scr.png

リップルエフェクト(クリックしたら波紋が出るあれ)の導入も行ったので、それについてもいつかまとめたい。

index.html
index.html
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><metahttp-equiv="X-UA-Compatible"content="ie=edge"><title>連番サポート</title><linkrel="stylesheet"href="main.css"><linkrel="icon"href="./img/icon16.png"sizes="16x16"type="image/png"><linkrel="icon"href="./img/icon32.png"sizes="32x32"type="image/png"><linkrel="icon"href="./img/icon48.png"sizes="48x48"type="image/png"><linkrel="icon"href="./img/icon64.png"sizes="64x64"type="image/png"></head><body><divid="content"><divid="primary"><textareaname="String_0"id="String_0"></textarea><divid="Number_1"><inputtype="number"name="Number_1_start"value="1">&#61;&gt;<inputtype="number"name="Number_1_end"value="1"></div><textareaname="String_1"id="String_1"></textarea><div><svgid="plus"x="0px"y="0px"viewBox="0 0 512 512"tabindex="0"><g><pathclass="st0"d="M359.244,224.004h-59.988c-6.217,0-11.258-5.043-11.258-11.258v-59.992c0-6.215-5.039-11.254-11.256-11.254
                        h-41.486c-6.217,0-11.258,5.039-11.258,11.254v59.992c0,6.215-5.039,11.258-11.256,11.258h-59.988
                        c-6.219,0-11.258,5.039-11.258,11.258v41.484c0,6.215,5.039,11.258,11.258,11.258h59.988c6.217,0,11.256,5.039,11.256,11.258
                        v59.984c0,6.219,5.041,11.258,11.258,11.258h41.486c6.217,0,11.256-5.039,11.256-11.258v-59.984
                        c0-6.219,5.041-11.258,11.258-11.258h59.988c6.217,0,11.258-5.043,11.258-11.258v-41.484
                        C370.502,229.043,365.461,224.004,359.244,224.004z"></path><pathclass="st0"d="M256,0C114.613,0,0,114.617,0,256c0,141.387,114.613,256,256,256c141.383,0,256-114.613,256-256
                        C512,114.617,397.383,0,256,0z M256,448c-105.871,0-192-86.129-192-192c0-105.867,86.129-192,192-192c105.867,0,192,86.133,192,192
                        C448,361.871,361.867,448,256,448z"></path></g></svg><svgid="minus"x="0px"y="0px"viewBox="0 0 512 512"class="disabled"tabindex="0"><g><pathclass="st0"d="M359.77,224.004H152.228c-5.928,0-10.732,4.804-10.732,10.73v42.535c0,5.926,4.805,10.734,10.732,10.734
                            H359.77c5.928,0,10.732-4.809,10.732-10.734v-42.535C370.502,228.808,365.697,224.004,359.77,224.004z"></path><pathclass="st0"d="M256,0C114.613,0,0,114.617,0,256c0,141.387,114.613,256,256,256c141.383,0,256-114.613,256-256
                            C512,114.617,397.383,0,256,0z M256,448c-105.871,0-192-86.129-192-192c0-105.867,86.129-192,192-192c105.867,0,192,86.133,192,192
                            C448,361.871,361.867,448,256,448z"></path></g></svg></div></div><divid="secondary"><divclass="submit_form"><buttonid="apply"class="submit">実行</button><buttonid="reset"class="submit">リセット</button></div><dl><dt>結果</dt><dd><textareaname="result"id="result"></textarea></dd><dt>結果をクリップボードにコピー</dt><dd><buttonid="clip">コピー</button></dd></dl></div></div></body><script src="main.js"></script></html>

main.css
main.css
@importurl('https://fonts.googleapis.com/css?family=Source+Code+Pro&display=swap');body{background-color:#222222;color:white;margin:20px0020px;display:flex;justify-content:center;}textarea,input[type="number"]{background-color:#333333;border:1pxsolid#666;color:white;margin:15px0;}textarea{padding:10px;width:20em;height:5em;display:block;font-family:'Source Code Pro',monospace;}input[type="number"]{width:7em;padding:3px;margin:015px;}textarea:hover,input[type="number"]:hover{border:1pxsolid#ffa6008e;outline:none;}textarea:focus,input[type="number"]:focus{border:1pxsolidorange;outline:none;}svg{fill:white;width:20px;height:20px;cursor:pointer;}svg:hover{fill:#ffa6008e;}#plus{margin:1em1em06.5em;}#minus{margin:1em6.5em01em;}#minus.disabled,#minus.disabled:hover{fill:gray;cursor:inherit;}.submit_form{margin:00030px;}.submit{color:white;width:80px;height:80px;background-color:transparent;border:1pxsolid#666;border-radius:50%;outline:none;margin:20px030px20px;display:inline-block;position:relative;z-index:1;overflow:hidden;}.submit:hover{border:1pxsolid#ffa6008e;}.submit:focus{border:1pxsolidorange;}#secondary{margin:40px000;}dl{margin-top:40px;}dd{margin-left:0;}#result{width:20em;height:15em;}@mediascreenand(min-width:768px){body{display:block;}#content{display:flex;}#secondary{margin:00080px;}#result{width:40em;height:20em;}}.ripple{position:absolute;width:0;height:0;border:none;border-radius:50%;background-color:#ffa600e1;z-index:5;pointer-events:none;animation-name:fadeOut;animation-duration:.5s;animation-fill-mode:none;}@keyframesfadeOut{0%{opacity:1;width:0px;height:0px;border:none;}40%{opacity:.3;}100%{opacity:0;width:100px;height:100px;transform:translateX(-50px)translateY(-50px);}}#clip{background-color:transparent;color:white;border:1pxsolid#666;border-radius:5px;outline:none;width:64px;height:24px;margin:10px0015px;position:relative;z-index:1;overflow:hidden;}#clip:hover{border:1pxsolid#ffa6008e;}#clip:focus{border:1pxsolidorange;}

JavaScriptでメイン処理を書く

アイコン周りのプラン

+アイコンで[文字列]{連番}のブロックを一つ追加
-アイコンで削除 (ただし初期状態のみこれ以上削除できないよう、クリックできないようにしている)

HTML要素の追加には、.appendChild()等を使っても良いのだが、今回は.insertAdjacentHTML()を使用した。パフォーマンス面で優秀らしい。(innerHTML より insertAdjacentHTML を使うより)今回は特にパフォーマンスが要求される場面ではないが、今後はよく使用することになりそう。

main_前半.js
letelement_count=1;document.querySelector('svg#plus').addEventListener('click',function(){if(element_count===1){document.getElementById('minus').classList.remove('disabled');}element_count+=1;letadding_element='<span class="block_content" id="Number_'+element_count+'"><input type="number" name="Number_'+element_count+'_start" value="1">&#61;&gt;<input type="number" name="Number_'+element_count+'_end" value="1"></span><textarea name="String_'+element_count+'" id="String_'+element_count+'" class="block_content"></textarea>'document.querySelector('#String_'+(element_count-1)).insertAdjacentHTML('afterend',adding_element);})document.querySelector('svg#minus').addEventListener('click',function(){if(element_count!==1){document.querySelector('span#Number_'+element_count).remove();document.querySelector('#String_'+element_count).remove();if(element_count===2){document.getElementById('minus').classList.add('disabled');}element_count-=1;}})

メイン処理のプラン

まず、例えば1-10の連番を振る際に、すべての欄を1-10にセットして・・・とするのは面倒なので、指定された数値範囲が最も大きいものに合わせて連番を振るようにした。
つまり、下のように、1カ所のみ1-10の範囲指定をすれば、それに合わせて連番の範囲が自動的に判断され、あとは左側の数字に合わせてそれぞれ連番を振っていけるようにした。

max.png

こんな感じでコーディング。。。

main.js
window.addEventListener('load',function(){letelement_count=1;document.querySelector('svg#plus').addEventListener('click',function(){if(element_count===1){document.getElementById('minus').classList.remove('disabled');}element_count+=1;letadding_element='<span class="block_content" id="Number_'+element_count+'"><input type="number" name="Number_'+element_count+'_start" value="1">&#61;&gt;<input type="number" name="Number_'+element_count+'_end" value="1"></span><textarea name="String_'+element_count+'" id="String_'+element_count+'" class="block_content"></textarea>'document.querySelector('#String_'+(element_count-1)).insertAdjacentHTML('afterend',adding_element);})document.querySelector('svg#minus').addEventListener('click',function(){if(element_count!==1){document.querySelector('span#Number_'+element_count).remove();document.querySelector('#String_'+element_count).remove();if(element_count===2){document.getElementById('minus').classList.add('disabled');}element_count-=1;}})document.getElementById('apply').addEventListener('click',(ev)=>{document.getElementById('apply').insertAdjacentHTML('afterbegin','<span class="ripple" style="left: '+ev.offsetX+'px; top: '+ev.offsetY+'px;"></span>');letwidth_loop=[];for(leti=1;i<=element_count;i++){width_loop.push(Math.abs((document.querySelector('input[name="Number_'+i+'_start"]').value-document.querySelector('input[name="Number_'+i+'_end"]').value)));}letloopNumber=Math.max.apply(null,width_loop);setResult(loopNumber);})document.getElementById('reset').addEventListener('click',(ev)=>{document.getElementById('reset').insertAdjacentHTML('afterbegin','<span class="ripple" style="left: '+ev.offsetX+'px; top: '+ev.offsetY+'px;"></span>');letallTextarea=document.querySelectorAll('#primary textarea');for(textareaofallTextarea){textarea.value='';}})functionsetResult(loopNumber){letresult=[];for(letn=0;n<=loopNumber;n++){letresult_string='';for(leti=0;i<=element_count;i++){if(i!==element_count){result_string=result_string+document.querySelector('textarea[name="String_'+i+'"]').value+(n+Math.min(document.querySelector('input[name="Number_'+(i+1)+'_start"]').value,document.querySelector('input[name="Number_'+(i+1)+'_end"]').value)).toString();}else{result_string=result_string+document.querySelector('textarea[name="String_'+i+'"]').value;result.push(result_string);}}}document.getElementById('result').innerHTML=result.join('\n');}document.getElementById('clip').addEventListener('click',(ev)=>{document.getElementById('clip').insertAdjacentHTML('afterbegin','<span class="ripple" style="left: '+ev.offsetX+'px; top: '+ev.offsetY+'px;"></span>');document.getElementById('result').select();document.execCommand("copy");})})

完成

そんな感じでできたのがこれです。
連番サポート (on GitHub)

res.png

レスポンシブ対応する

$
0
0

レスポンシブ対応する

思ったよりめちゃ簡単だった.

HTML

HTMLのヘッダーに以下を追記.

<metaname="viewport"content="width=device-width,initial-scale=1.0,minimum-scale=1.0">

width=device-width

でデバイスの幅を取得する.

CSS

CSSに以下追記.
PC向けの場合

@mediascreenand(min-width:767px){/*ウィンドウ幅が767px以上の場合に適用*/#hoge{hoge:foo;}}

SP向けの場合

@mediascreenand(max-width:479px){/*ウィンドウ幅が最大479pxまでの場合に適用*/#hoge{hoge:foo;}}
Viewing all 8499 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>