20191201のCSSに関する記事は7件です。

JavaScriptでチャットボットを作る

JavaScriptでチャットボットを作る

はじめに

今回作るのは、簡単に質問応答してくれるチャットボットです。
言語はHTML,CSS,JavaScript(約50行)です。
応用次第で、より複雑なものを作ることも、もちろん可能です!

目標

  • 自分の名前を送信したら、それを含めたメッセージが返す
  • 自分にランダムなメッセージを返す
  • (様々な会話パターンを作ってみる)
  • (相手から選択肢のボタンを送信され、それぞれに応じた結果を返す)

この記事の対象者

JavaScriptで様々なものを作ってみたい人。チャットボットやAIに興味がある人などなど。
チャットボット

ここでは必要最低限の部分だけ説明します。詳細は下のCodePenをご覧ください

See the Pen チャットボット by MF3PGM (@masa_mf3rs) on CodePen.

HTML

チャットの画面にあるulに(JavaScriptで)liを追加していく仕組みです。

HTML
<!--画面-->
<div id= "field">
    <ul id= "chat-ul"></ul>
</div>

<!--入力場所,送信ボタン-->
<div id= "input-field">
    <input type= "text" id= "chat-input">
    <input type= "button" value= "Send" id= "chat-button" onclick= "btnFunc()">
</div>

CSS

☞ポイント

  • ulの子要素li(背景色:緑または白の部分)に直接文字を書いてもいいですが、デザイン上、今回はliの子要素divに文字を書いていきます。(吹き出しテキストのpaddingやline-height,改行などが複雑になるのを防ぐため)

  • 話す人が自分の場合、liに chat-rightクラスを付与し、話す人が相手ならchat-leftクラスを付与します。

CSS
/*チャット画面のスクロール設定*/
#field{
    /*横向きのスクロール禁止*/
    overflow-x: hidden;
    /*縦向きのスクロール許可*/
    overflow-y: scroll;
    /*スマホでは指でスクロール*/
    -webkit-overflow-scrolling: touch;
}

/*自分の吹き出し*/
.chat-right{
    margin-left: auto;
    margin-right: 25px;
    background: #A4E496;
}
/*相手の吹き出し*/
.chat-left{
    margin-left: 25px;
    background: #FFF;
}

JavaScript

今回は、相手のメッセージは全て2秒遅れにします。

☞ポイント

  • 相手が返信する度に、chatCountを1ずつ足していきます。自分がテキストを入力し、送信ボタンを押した瞬間のchatCountの値に応じて、配列から特定のメッセージを選び返信させます。
  • 今回作った関数は、画面に吹き出しを描画するoutput()と、送信ボタンを押したときのbtnFunc()です。
JavaScript
//相手の返答内容
const chat = [
    'Hello ! Welcome to AI chat !',
    'What is your name ?',
    'How are you today ?',
    [['Alright !'], ['Oh really!'], ['Ok!']]//ランダムな返答
];

//相手の返信の合計回数(最初は0)
//これを利用して、自分が送信ボタンを押したときの相手の返答を配列から指定する
let chatCount = 0;

//画面への出力をする関数(valはメッセージ内容,personは誰が話しているか)
function output(val, person) {
    //中略
    if(person === 'other'){
        //中略
        chatCount++;
    }
}

//自分がテキストを入力し、ボタンを押したときの関数
function btnFunc() {
    //中略
    output(inputText.value, 'me');
    //中略

    //相手の送信の合計回数に応じて次の返信を指定
    switch(chatCount) {
        //もし相手のトーク数が2個の時に送信ボタンが押されたら、
        //自分の名前を含んだメッセージと、chat配列の2(3個目)が返信
        case 2:
            output('Hi, ' + inputText.value + ' !', 'other');
            setTimeout( ()=> {
                output(chat[2], 'other');
            }, 2000);
            break;

        //もし相手のトーク数が4個の時に送信ボタンが押されたら、
        //chat配列の3(4個目)のランダム番目が返信
        case 4:
            output(chat[3][Math.floor(Math.random() * chat[3].length)], 'other');
            break;
    }
}

//最初に相手から話しかけられる
output(chat[0], 'other');
setTimeout( ()=> {
    output(chat[1], 'other');
}, 2000);

おわりに

チャットボットを作りたい。。しかし、どのサイトを調べても、ライブラリやサーバ,ChatUIなどを使った難しいものばかりでした。そんな中、ピュアなJavaScriptだけで作れないかと数日間試行錯誤し、やっと完成しました。
まだ初心者なので、アドバイス等あれば教えていただければと思います。
そして、この記事が皆様にお役に立てれば幸いです。

参考書

本当によくわかるJavaScriptの教科書P.122(outputメソッドの2つの引数を使った部分)

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

プログラミング初学者が2ヶ月半で630時間勉強した話

はじめに

Qiita初投稿です。記事を書くのは初めてなので、上手く書けるかわかりませんが、どうか温かい目で閲覧いただけると幸いです。また、まだまだ勉強中で下記の説明の中で理解が及んでおらず、間違っているところもあるかと思いますので、あらかじめご容赦下さい。
これからプログラミングを学習しようと考えている方や、プログラミングを学習中の方の励みになればと思ってこの記事を投稿させていただきます。

プログラミングに出会うまで

私は、沖縄の大学を卒業後、地元の鹿児島に戻り実業団選手として陸上競技をしていました。その後、工業機械の製造・メンテナンス、建設業・設備業の仕事をしてきました。しかし、年齢を重ねるにつれて肉体的にしんどくなり、何かいい仕事はないかと考えていたところ、学生時代の先輩がSNSでプログラミングスクールの告知をしていたため、スクールを受講してみようと思いました。

スクールについて

概要

スクールは沖縄のCODEBASEに通いました。こちらのスクールでは、自習ベースで学習し、毎週月曜と木曜(祝日を除く)の19:00〜22:00の週に2回、全18回の講義を実施し、自習した内容の確認や不明点や補足を講義で質問・説明する形式です。
また、スクール卒業までにSinatraでwebアプリケーションを制作し発表するというものでした。

スクール面談

早速申し込みをして、面談をすることになりました。スクールは定員が決まっており、面談ではどうして受講しようと思ったか、勉強時間は確保できるか、最後まで通い続ける自身はあるか、スクール卒業後はどうなりたいか等の話をしました。私は鹿児島にいましたが、skypeでオンライン面談をさせていただき、自分の気持ちを話させていただきました。

スクールに通い始めるまでにやったこと

無事受講させていただくことになり、受講までにprogateで学習を進めてほしいというメールが届きました。progateはスクール側でアカウントを用意してくれました。
受講まで2週間ほど期間があったので、HTML、CSS、Javascript、jQuery、Rubyを1周しました。
HTML、CSSは、学生時代に講義で学んだことがあったため、思い出しながら学習しました。その他に関しては、あまり理解できませんでしたが、とりあえず触っておこうと思い、進めた感じです。

スクール初回

講義内容

ついにスクールが始まりました。私は沖縄へ移動し、宿泊しながらスクールに通いました。仕事はフリーランスだったため、スクールに通っている間は、プログラミングに集中しようと思い一時休業しました。
スクール初日はslackという業務用のLINEみたいなアプリの紹介、使い方等を学びスクールのカリキュラム説明を聞きました。また、初日は台風でした笑

次回講義までの予習内容

HTMLとCSSの学習をする指示があったため、再度progateで学習しました。また、実際に簡単なWebページを作成し、CSSでスタイルを適用させるまでやってみました。

ここまでの学習時間

5時間

スクール2回目

講義内容

ChromeとVisual Studio Codeを使用するため、これらをインストールし、簡単な使い方の説明を聞きました。
その後、Webの仕組みやHTML、CSSについて学習しました。それぞれバージョンがあり、現在はHTML5とCSS3を使って開発するということを学びました。講義では具体的には、ブラウザに文字を表示させる方法、文字の色を変更する方法、画像を挿入する方法等でした。
その後、実際に簡単なWebページを制作しました。私は、2回目の講義までに制作していたWebページがあったため、さらにそのページを作り込みました。具体的には、CSSのメディアクエリを使い、レスポンシブに対応するようにデザインしました。制作していると講師の方から発表してほしいと声をかけられたため、みんなの前で発表させていただきました。
ブラウザ、Webがどのように進化したかを視覚的に見ることができるこちらのサイトが面白いと思いました。

次回講義までの予習内容

CSSフレームワークのBootstrap4の使い方を調べる、Javascript、jQueryの勉強をするという指示があったので、progateでの学習、Bootstrapについては、googleで検索し、どのようなものなのかを調べました。
また制作していたWebページにBootstrap4を導入して制作し直したり、公式のドキュメントを見て使い方を勉強しました。

ここまでの学習時間

40時間

スクール3回目

講義内容

実際にBootstrapを導入してwebサイトをきれいにデザインする方法を学習しました。私は、予習していたので、すんなり使うことができました。Bootstrapでレスポンシブ対応させたり、カルーセルで画像をスライド表示させたり、モーダルを実装したりしました。
Bootstrapを使うことで、デザイン時間を短縮でき、かつデザインが苦手でも、それっぽいサイトを作れるのはすごくいいなと思いました。

次回講義までの予習内容

引き続きJavascript、jQueryの学習を進める、Rubyの学習を進めるとの指示だったため、それぞれprogateで学習しました。

ここまでの学習時間

62時間

スクール4回目

講義内容

Javascript、jQueryを使って、Webサイトに動きをつける学習をしました。私個人の感想としては、このあたりから少し難しくなっていったと思います。
具体的には、Javascriptのバージョンについてや、記述方法、Javascriptライブラリの種類等を学びました。ライブラリの中でも、初心者が学習しやすいjQueryを使ってボタンを押すとスクロールしたり、クリックするとメニューが開くアコーディオンを作ったり、タブパネルを作ったりして実際にサイトに動きをつけてみました。

次回講義までの予習内容

引き続きJavascript、jQueryの学習を進める、Rubyの学習を進めるとの指示だったため、それぞれprogateで学習しました。

ここまでの学習時間

114時間

スクール5回目

講義内容

前回の続きで、Javascript、jQueryの学習をしました。また、非同期通信のAjaxについても学習しました。Ajaxについては、具体的な例を出してくれて、twitterのいいねボタンやgoogleマップの拡大縮小、チャット機能等がそれに当たるということを知りました。
Javascriptのデバッグ方法(ブラウザのコンソールを使う)についても学習しました。

次回講義までの予習内容

中間発表のWebページ制作を進められる人は進めておいてほしいという指示もあったので、私は制作を進めました。

ここまでの学習時間

170時間

スクール6回目

講義内容

この日は各自オリジナルサイトの制作を進めました。わからないところがあったら講師の方に質問したり、アドバイスを貰ったりして、制作しました。これまで学んだことが結構盛りだくさんだったので、どんなデザインでどんなアニメーションを実装するかを考え、制作を進めました。

次回講義までの予習内容

中間発表オリジナルサイト制作の指示があったため、これまで学習した内容を生かして制作を進めました。

ここまでの学習時間

196時間

スクール7回目

講義内容

学習のハマる仕掛けや、2回目の講義よりさらに詳しくWebのしくみについて学習しました。具体的には、Webページが表示されるまでに、サーバーとクライアントでどのようなことが行われているのか、サーバーにはどのような種類があるのか等を学びました。
またWebサイト(静的)とWebアプリケーション(動的)の違いについても学習しました。このあたりから、Webアプリケーションを制作するにあたっての導入編だったのかなと思います。

次回講義までの予習内容

前回同様、中間発表のオリジナルサイト制作の指示があったため、引き続き制作を続けました。また、gitの学習をする指示されたのでprogateのgitを学習しました。

ここまでの学習時間

213時間

スクール8回目

講義内容

前半はWebサイト制作をしてわからないところを質問し、残りの1時間で制作したオリジナルサイトを発表しました。私は、知人がラーメン屋をやっているため、宣伝用のオリジナルサイトを制作しました。
CSSフレームワークはmaterializeというマテリアルデザインベースのフレームワークを使い、jQueryのライブラリbx-sliderを使って要素をカルーセルスライダーにしたり、ウィンドウをスクロールすることで要素をふわっと表示させるアニメーションを付けたりしました。
また、制作したサイトをgitにpushして実際に公開するところまで行いました。また、gitを使うことで、バージョン管理したり、チーム開発で使用したりできるということだったので、すごい便利な機能だと思いました。

次回講義までの予習内容

次回の講義からRubyに入るとのことだったので、再度progateのRubyを学習しました。私はトータルで5周くらいしたと思います。

ここまでの学習時間

247時間

スクール9回目

講義内容

この回からWebアプリケーションを制作するための学習が始まりました。こちらのスクールではRubyを使って制作するということでした。
なぜRubyを使ってWebアプリケーションを制作するのか理由として、

  1. Rubyは世界で使われている開発言語の1つであるため
  2. 日本語の記事が多いため
  3. 記法がシンプルで書きやすいため

という理由のようです。
日本語の記事が多いためというのが一番の理由みたいです。なぜ、日本語の記事が多いのか、それはRuby言語の開発者が日本人だからということでした。また、公式のドキュメントも非常に充実しており、卒業後に学習を進めていくにあたり、Railsチュートリアルというものもあるということから、Rubyを学習するカリキュラムを組んでいるようです。

Ruby初回の講義は、計算・演算、変数、条件分岐、関数、ループ文について学習しました。計算・演算では演算子(+ - * / %)を使って計算したり、計算式を変数に代入したりしました。
条件分岐はif文を使って表示させる内容を分岐させたり、条件によって計算方法を変えたりしました。
関数は、何度も使う処理を定義して呼び出すだけで結果を表示することができるので便利な機能だと思いました。
ループ文は1から100までの数字を出力する時に、putsを100回書くのではなく、eachやtimesを使って同じ処理を繰り返すことで楽にプログラムが書けることを知りました。
またプログラムをデバッグするgemのpryを使って、変数の値がどうなっているか実際に値を取り出して説明してくれたりしたので、少しはイメージしやすかったです。
これまで学習してきたHTML、CSS、JS等のフロントエンドと違ってサーバーサイドの学習はこれまで以上に難しかったです。

次回講義までの予習内容

FizzBuzz問題というプログラムを学習する上で、一番最初に練習問題として作るプログラムを作ってくるようにとの課題が出たので、そのプログラムを制作しました。
前回までにかなりprogateで学習していたので、Sinatraについても予習しておこうと思い、paizaラーニングを個人的に登録し、Sinatraの学習も同時に進めました。また、Sinatraでの投稿、編集・更新、削除できる簡易的な掲示板のようなものを実際に作ってみようと思い、paizaラーニングを参考にしながら制作を進めました。

ここまでの学習時間

265時間

スクール10回目

講義内容

クラスとインスタンスについて学習しました。クラスで抽象的なものを定義して、インスタンスでより具体的なものを作成するということを学びました。クラス内で変数を呼び出すにはインスタンス変数を作ること、@をつけることでインスタンス変数にできること等を教わりました。インスタンスを作成する際にはnew,newしたときに自動的にinitializeメソッドが呼び出される等も教わりました。
また、モジュールやライブラリ、フレームワークについての説明もありました。
最後にSinatraを導入してHello Worldを表示させるところまで講義で説明があり、このあたりの理解度としてはまだまだ低いですが、最初はとにかく難しかったです。

次回講義までの予習内容

次回からSinatraを使ってWebアプリケーションを制作していくため、Sinatraについて学習する指示があったので公式ドキュメントやpaizaラーニングを使って学習しました。また、個人的に掲示板を作ってみて、なんとなく理解できてきたので早めに卒業制作を始めました。また、データベースについても学習しようと思い、progateのSQLを学習しました。

ここまでの学習時間

329時間

スクール11回目

講義内容

この回から、Sinatraを使ったWebアプリケーションの制作について学習しました。講義では前回の終わりに少し触った程度だったのでまずは、Sinatraのインストールから説明があり、Hello Worldを表示させるまでを実行しました。Sinatraはファイルを編集するたびにサーバーを再起動し直さないといけないので、reloaderを追加する説明があったので、快適に開発できるようにしました。
講義の中では、GETリクエストでエンドポイントを作成したり、テンプレートエンジンのerbファイルを作ったり、layout.erbに共通部分をまとめたり、画像やCSS等の静的ファイルをpublicフォルダにまとめたりしました。
実際に手を動かしてWebアプリケーションを制作していくと、Rubyで学んだことがだいぶ理解できるようになっていきました。

次回講義までの予習内容

今回の講義で学んだことをしっかり復習しておくことと、私は卒業制作を始めていたので、いろんなサイトを参考にしながら制作を進めていきました。この頃にはGET、POSTについてだいぶ理解できていました。また、実際にPostgreSQLでデータベースを作成して、接続し、データの投稿・更新等ができるようになりました。

ここまでの学習時間

383時間

スクール12回目

講義内容

前回の復習をして、続きを学習しました。GETとPOSTの違いや使い分けについて聞き、URLにどう影響するかを実際に見せてくれました。
また、実際に入力した内容を受け取るためにparamsを使うことや、ファイルアップロードの方法、ログイン機能を実装するためにクッキーやセッションの説明等、この回の講義はSinatraでアプリケーションを作る上で一番大事な回だったと思います。

次回講義までの予習内容

今回の内容を理解できるように復習をしっかり復習しておく、SQLについての学習をする指示があったので、それぞれ復習とprogate、paizaラーニングでSQLを学習しました。
個人的には、卒業制作を進めて、8割方できていました。このあたりからgemを使っていろんな機能を追加してみようと思い、どんなgemがあるのかをrubygemsで見てみたり、調べたりして、実装していきました。
また、講義以外でも学んでみたいと思い、講師の方のコミュニティ勉強会に参加してみました。そちらは、Vue.jsについての勉強会でした。

ここまでの学習時間

408時間

スクール13回目

講義内容

データベースのPostgreSQLを使ってデータベースを作る講義でした。データベースにアクセスしてSQL文でデータを追加、更新、削除、検索する学習がメインでした。SQLインジェクションやXSS等セキュリティに関することにも触れました。
またgemのpgを使ってSinatraでデータベース接続をしてデータを保存する方法についても学習しました。
SQLに関しては、学生の時に少し触ったことがあったので、簡単に学習することができたかなと思います。

次回講義までの予習内容

簡単な掲示板を作成する、写真を投稿する掲示板を作成するとの指示があったので、そちらの課題を進めました。
個人的には、SQLインジェクションが気になったので、実際にSQLインジェクションできる掲示板を作ってどのような動きをするのか確認してみました。実際に攻撃を仕掛けてみると、データが全部削除されたり、ユーザー情報を盗むことができたりしたので、対策は大事だなと思いました。
実際に作った掲示板

ここまでの学習時間

433時間

スクール14回目

講義内容

引き続きデータベースの講義でした。データベースの種類や条件等を学びました。
データベースには主に、

  • PostgreSQL
  • MySQL
  • MariaDB
  • OracleDB
  • SQL Server
  • SQLite3
  • Access

これらの種類があることを知り、たくさんあるんだなと思いました。またテーブル同士の関係性には1対1、1対多、多対多があり、設計をどれだけ上手くできるかが重要ということを学びました。
講義の後半では、複数のチームを作って、ワークショップ形式で実際に提供されているサービスのテーブル構成やリレーションについて受講生同士で話し合い、ER図を書き出して発表しました。

次回講義までの予習内容

データベースの復習と卒業制作のアイデアを考えてくる指示でした。
個人的には、卒業制作が終わっていたので、progateとpaizaラーニングのRuby on Railsを学習しました。Sinatraで学習した内容がMVCに分かれたという認識を持つことができたので、制作の基礎は比較的簡単に理解することができたかなと思います。

ここまでの学習時間

506時間

スクール15回目

講義内容

Webアプリケーションの開発手法について学習しました。開発手法は主に

  • ウォーターフォール型モデル
  • アジャイル開発型モデル

があるということを学びました。また、開発していく中で便利な設計ツールを紹介してくれたり、実際にサンプルを見せてくれたりしました。
後半は、前回と同様ワークショップ形式で、ページ遷移図やER図を書き出しました。私は講義の中で紹介されたMySQLWorkbenchを使って実際にER図を書いてみることにもチャレンジしてみました。

次回講義までの予習内容

次回から卒業制作を各自進めるとのことだったので、アイディアを考えてくるようにとのことでした。
個人的には、以前外部のVue.js勉強会に行った際に、話している内容が全くわからず、悔しかったのでVue.jsを学習しました。

ここまでの学習時間

540時間

スクール16回目、17回目

講義内容

各自卒業制作を進めました。また、自信がない方向けに別室で講義形式でWebアプリケーションを制作する手順を解説してくれたので、かなり手厚いサポートだなと感じました。
私が制作したWebアプリケーションは、ActionMailerを使いお問合せフォームを設置しており、rbファイルに直接重要な情報を書き込んでいたため、環境変数について講師の方に個別で教えていただきました。
また、最後の発表はみんなを驚かせようと思い、もう一つ卒業制作をしました。

ここまでの学習時間

568時間(16回目)、605時間(17回目)

スクール18回目

講義内容

卒業制作発表を行いました。私はスポーツポータルサイトを制作しました。具体的には、管理者が様々なスポーツ情報を掲載して公開するサイトです。
実装した機能としては、
- 画像を投稿するとカルーセルスライダーに追加される
- 大会情報を投稿・編集・更新・削除(CRUD)できる
- 絞り込み検索
- キーワードあいまい検索
- 管理者と編集者でアクセスできるページの権限を与える
- フラッシュメッセージ
- メールフォーム(ActionMailer使用)
- パスワード暗号化(bcrypt使用)
- カテゴリー分け
- 年別月集計
- リッチテキストエディタ設置(ckeditor)
- バリデーション設定
- エラーメッセージ表示
- その他多数

またもう一つ制作したアプリケーションはフロントをNuxt.js、サーバーサイドをRuby on Railsで制作し、axiosでデータを取得させるということにもチャレンジしました。

講師やサポートで入ってくれていた方々はすごく驚いてくれました。

総学習時間

632時間

最後に

この2ヶ月半で632時間学習し、1日の学習平均時間は約8時間半でした。
今回、プログラミングについてほとんど分からなかった私が、ここまでできるようになったことは、かなり自信になりました。
私は、性格的に何においてもやり込む、極めることが好きで、これまでの職業が職人向けの仕事だったため、プログラミングは向いていたのかなと思います。
もし、プログラミングを学習してみたいと考えている。でも、学生の頃にプログラミングの勉強をしていなかったから無理等と決めつけないで、一度勉強してみて下さい。
プログラミングは、どれだけ学習をやったかで知識として身についていくので、我らが講師@saboyutakaさんの未経験からRuby on Railsを学んで仕事につなげるまでの1000時間メニューの記事を参考にしながら、学習習慣をつけてエンジニアとして働くことができるように日々精進していきたいと思います。

卒業制作リンク

卒業制作発表スライド
卒業制作ソースコード(Sinatra)

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

css3のdropshadowが凄かった!!

輪郭に沿って影を付けたかった!

box-shadowは駄目なの??

SVGにbox-shadowを指定すると、想像とは違う出来上がりに:innocent:

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

.icon-location-box {
  width: 100px;
  box-shadow: 10px 10px 10px rgba(0, 0, 0, 0.6);
}

dropshadowを使ってみた!

内側にも影が付いた:relaxed:

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

.icon-location {
  width: 100px;
  filter: drop-shadow(10px 10px 10px rgba(0,0,0,0.6));
}

IE11は未対応???

can I useに拠るとIE11は未対応の様です:scream:

またしてもIE11に足止めを食らうのか・・・。

ブラウザの対象範囲に拠っては使い所満載なので凄く良いプロパティだと思います(小並感)

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

HTMLテーブルのborder優先順位

経緯

HTMLテーブルのスタイルを”border-collapse: collapse”にしたとき
borderをセルをフォームの入力によって色を変えたら上手くいかなかった。
調べてみるとスタイルの指定の仕方で優先度があったので備忘録として残します。

結論

優先度順
1.border-hidden
2.border-width(太いほど優先)
3.border-style(double、solid、dashed、dotted、ridge、outset、groove、insetの順に優先)
4.上記が同じ場合はテーブル内でより左にあるもの、上にあるものの順で優先されます。
5.border-style: none (もっとも優先順位の低い状態)

以上、閲覧ありがとうございました。

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

高さの違うコンテンツを"いい感じ"に動的にグリッド表示したい! ライブラリ無しで!

ハローワールド。

Masonry, magic grid, etc...。みなさんはこのライブラリを知っていますか?
これらは、グリッドレイアウトを実現するためのライブラリです。

通常、CSSのflexboxやgridを使えばグリッドレイアウトは可能ですが、これらのライブラリは高さの違うコンテンツを"いい感じに"表示してくれます。

例えば、Magic Gridであれば以下のようにフレキシブルなグリッドレイアウトを実現してくれます。(以下のGifはMagic GridのGithubのReadmeより引用)
Magic Grid Sample.gif

Flexboxでグリッドレイアウトを作ると高さが一定になってしまうため妙な余白ができてしまいます。
かといってGridを利用するときには事前に高さとか配置とか決めておく必要があるので動的に表示するのはなあ...ということで、こういったライブラリを利用していました。

しかし、これらのライブラリもメンテナンスがされてなかったり、TypeScriptのtypeがなかったり、実装を見るとleftとtopやtransformで座標を指定したりと手放しで喜んで利用したい、というライブラリではありませんでした(個人の感想です)。

なので、今回ライブラリ無しで、できる限りCSSだけでこれを再現したかったので投稿いたしました。
実際にはCSSだけではできませんでしたが。

もっと簡単にできるなら教えて下さい(切実)

完成品

See the Pen Card Grid Layout without Library by sa2taka (@sa2taka) on CodePen.

説明

上記の動作はCSSのGridを利用して、ほぼ無理やり実現しています。

css

cssでは大したことはやってないのであまり詳しい説明はいらないかもしれません(jsもそうですが)

#grid

まず最初に上記のhtmlでは

<div id="grid">
</div>

となっている部分です。このgridは以下のスタイルが適用されています。

#grid {
  display: grid;
  grid-auto-rows: 20px;
  grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
}

display: gridの説明はいいとして、grid-template-columns: repeat(auto-fit, minmax(200px, 1fr))ですが、詳細はMDNに任せるとして(grid-template-columns, repeat)、結果的に言えばウィンドウの横幅に合わせて列数を"いい感じ"にフィットさせてくれるやつです。これのおかげで随分フレキシブルな動きが可能です。

今回重要となるのがgrid-auto-rowsです。MDNによると、

grid-auto-rows と grid-auto-columns プロパティで、暗黙的なグリッドに作成されたトラックのセットサイズを定義することもできます

ということです。明示的、暗黙的と表現されていますが、動的なコンテンツに対するサイズ、今回はrowsなので縦のサイズを定義するという意味と捉えています。

補足程度ですが、grid-template-rowsでもいいです。若干違いはありますが、だいたいおんなじ見た目になります。もしかしたらtemplateの方が良いのかもしれません。

.item

次にitemクラスですが、こちらは

.item {
  min-width: 80px;
  margin-left: 8px;
  margin-top: 8px;
  box-sizing: border-box;

  background: green;
  color: white;
}

と、大したことはやってないので説明は割愛します。

ちなみに、box-sizing: border-box;を指定しておかないと予想通りの表示にならなかったりします。多分。

JavaScript

以下にJavaScriptの全体のコードを載せますが、必要なのはaddItemだけです。

let index = 1;
const addItem = () => {
  const height = randomNum();
  const grid = document.querySelector('#grid');
  const item = document.createElement('div');
  item.setAttribute('class', 'item');
  item.setAttribute('style', `height: ${height}px;grid-row: span ${Math.ceil(height / 20)};`);
  item.innerHTML = index;
  index += 1;
  grid.appendChild(item);
}

const randomNum = () => {
  const min = 40;
  const max = 200;
  return Math.floor(Math.random() * (max - min + 1) + min)
}

window.addEventListener('load', () => {
  for (let i = 0; i < 10; i++) {
    addItem();
  }
  document.querySelector('#addItemButton').addEventListener('click', () => {
    addItem();
  })
})

addItem

以下にaddItem部分だけ載せます

const addItem = () => {
  const height = randomNum();
  const grid = document.querySelector('#grid');
  const item = document.createElement('div');
  item.setAttribute('class', 'item');
  item.setAttribute('style', `height: ${height}px;grid-row: span ${Math.ceil(height / 20)};`);
  item.innerHTML = index;
  index += 1;
  grid.appendChild(item);
}

単純に#griddiv.itemを追加するだけのコードですが、重要なのはここです。

item.setAttribute('style', `height: ${height}px;grid-row: span ${Math.ceil(height / 20)};`);

style要素に高さとgrid-rowを書き込んでいます。heightはいいとして、grid-rowは何でしょうか。

MDNによれば、gridのアイテムの実際の高さを決める項目です。grid-rowは実際には絶対的に数字を入れる必要がありますが、spanを入れることで指定した値分の高さを埋めるように自動的に位置が決まります。

例えばgrid-row: 3とした場合はrowが3から始まりますが、grid-row: span 3とした場合はgridの高さが3になるように自動的に入り込みます。ちなみにこの高さの単位は、先程指定したgrid-auto-rowsの値になりますので、span 3であれば60pxになるようにGridが埋まります。

つまり、ここをgrid-row: span 高さ / grid-auto-rowsで指定した値とすれば高さを"いい感じに"指定しつつ、配置もCSSのgridの力を借りて"いい感じに"してくれるようになります。

言葉だけでは理解しづらいかもしれませんが、ChromeのDeveloper ToolsのElementsから確認すると案外わかりやすいです。
Gridの詳細表示
CSSのgrid-auto-rowsで20pxごとにラインを引いていきます。それが紫のラインですね。そして、grid-rowで高さを決めることで、gridの強さを活かしつつ高さも"いい感じに"表示できるって感じですね。

ただ、残念ながらウィンドウ幅を動かしたときに、Magic-Gridのようにカラムが動くようなアニメーションは付きません。悪しからず。

最後に

今回の説明ではMDNを利用しつつ軽く説明していますが、私もGrid初心者みたいな存在なので、解釈違いなどあるかもしれませんし、実はGridをグリグリ動かせばjavascriptさえ使わずに実現できるかもしれません。magic-grid使ったほうが良くね

急ぎ足で解説しましたので乱文ですが、以上となります。
ツッコミ、"こんな方法あるよ"、"このライブラリ便利だよ"等あったらお願いします。

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

CSSでアドベントカレンダー作ったよー

この記事は CSS Advent Calendar 2019 1日目の記事です。
アドベントカレンダーのイベントなので、「アドベントカレンダー × CSS」 の内容で書きます( ✌︎'ω')✌︎

そもそもアドベントカレンダーってなに

アドベントカレンダー (Advent calendar) は、クリスマスまでの期間に日数を数えるために使用されるカレンダーである。待降節の期間(イエス・キリストの降誕を待ち望む期間)に窓を毎日ひとつずつ開けていくカレンダーである。すべての窓を開け終わるとクリスマスを迎えたことになる。

『ウィキペディア日本語版』(2018年11月23日 (金) 09:37 UTC)

Qiitaのアドベントカレンダーに参戦している人ならご存知の方が多いと思いますが、アドベントカレンダーはクリスマス当日までのカウントダウンを楽しむものとして存在しています。サンタさーん!こっちですよー!!!
家庭のアドベントカレンダーは中身にお菓子が入っていることが多いらしいですね。私はやったことないのですが

CSSで作ってみた

クリスマスが待ち遠しいのでCSSでカレンダー作ってみました。見た目だけ!!!
画像は使っていません。
日付をクリックすると扉パカパカします。中身にプレゼントが入っています。プレゼントもCSSです。
中身のプレゼントにカーソル当てるとゆらゆら揺れます。

※ スマホで見ると多少バグが発生するかもしれないですmm


See the Pen
CSS Advent Calendar
by Deren (@deren2525)
on CodePen.


どう作ってるの

あまり綺麗なコードとは言えないのですが、せめてここだけでも...という部分を紹介します(させてください)

日付ボックス開けたり閉めたりしてる部分

CSS-Advent-Calendar-2019-12-01-001

チェックボックス乱用しています。
日付の扉をチェックボックスに紐づいた<label>の中に入れることで、扉をクリックすると開いたり閉じたりすることができます。
チェックボックス自体は、あると格好悪いので隠しています。

index.scss
// クリック処理の部分のみ抜粋
.box { // input
  display: none;
  &:checked {
    + label {
      .door { // 日付の扉
        transform: rotatey(-5deg) rotatex(85deg);
      }
    }
  }
}

HTML 部分は下記。Pug で書いています。いつもお世話になっております。
ここって Pug のシンタックスハイライトつかないんですね、少し見辛い...

index.pug
- for (var i = 1; i <= 25; i++) // 25日分
  .advent-calendar__item
    input.box(type="checkbox" name=`${i}` value=`${i}` id=`${i}`)
    label(for=`${i}`)
      .contents
       // この中でプレゼントごにょごにょ作ってる
      .door: span #{i} // 扉

ちなみに PugHTML に変換されると以下のようになります。25日分書くととても長いので1日分だけ

index.html
<div class="advent-calendar__item">
  <input class="box" type="checkbox" name="1" value="1" id="1">
  <label for="1">
    <div class="contents">
      <!-- この中でプレゼントごにょごにょ作ってる -->
    </div>
    <div class="door"><span>1</span></div>
  </label>
</div>

なんか寂しいから雪を降らせる

CSS-Advent-Calendar-2019-12-01-002

なんか寂しかったのでCSSアニメーションで雪を振らせました。

2の倍数番目、3の倍数番目、4の倍数番目...てかんじで雪がバラバラ落ちてくれるようにしています。
アニメーション時間とかはめちゃくちゃに適当です。

style.scss
// アニメーション部分のみ抜粋

@mixin snow-animation($duration, $delay) {
  -webkit-animation: #{$duration}s ease-in-out #{$delay}s infinite snowMove;
  animation: #{$duration}s ease-in-out #{$delay}s infinite snowMove;
}

.snow-ball {
  @include snow-animation(6, 0);
  &:nth-of-type(2n) {
    @include snow-animation(5, 2);
  }
  &:nth-of-type(3n) {
    @include snow-animation(5, 1);
  }
  &:nth-of-type(4n) {
    @include snow-animation(5, 3);
  }
  &:nth-of-type(5n) {
    @include snow-animation(5, 5);
  }
  &:nth-of-type(6n) {
    @include snow-animation(5, 4);
  }
  &:nth-of-type(7n) {
    @include snow-animation(6, 2);
  }
  &:nth-of-type(8n) {
    @include snow-animation(6, 3);
  }
  &:nth-of-type(9n) {
    @include snow-animation(6, 1);
  }
}

@keyframes snowMove {
  0% {
    transform: translateY(-10px);
  }
  100% {
    transform: translateY(170px);
  }
}

ここもPugさんにだいぶお世話になっている気がする...

index.pug
- for (var i = 0; i < 35; i++) // 雪の数
 .snow-ball(style=`left: ${12*i}px;`) 

おわり

CSSだけで作らないといけない理由は正直ない
サンタさーん!プレゼント待ってます!メリークリスマス〜〜

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

鉄道ポモドーロタイマーなるものを作ったー。

こんにちは。N高等学校1年次のなっかのうです!

N高アドベントカレンダー、sifue先生の次ですが頑張りたいと思います。

何作ったの?

今回は、勉強法でおなじみの「ポモドーロタイマー」に、

鉄道の駅名をくっつけた「鉄道ポモドーロタイマー」なるものを作成しました。

image.png

GitHub

実際にやってみる

どんなものや?

ポモドーロタイマーとは、

「勉強と休憩の時間を設定して繰り返すことでより集中できるようになる」

勉強法のためのタイマーです。

そこで、私は「駅間所要時間ってバッチリじゃないか?」と思い、

休憩駅と勉強駅を繰り返す鉄道ポモドーロタイマーを作成しました。

image.png

利点

基本的にはポモドーロタイマーと一緒ですが、

現在の駅名などが表示されるため、

今どのくらいかなどがわかりやすく、

とても実用性のあるものになっています。

コード(長いので一部)

    function timermain(){
        let now = new Date();
        let diftime = (now.getTime() - start.getTime());
        let point = Math.floor(diftime / 100);
        let point2 = Math.floor(point % 10);
        let point3 = parseInt(9)-Math.floor(point % 10);
        let sec = Math.floor(diftime / 1000);
        let secsec = Math.floor(sec % 60);
        let sec3 = parseInt(59)-Math.floor(sec % 60);
        let min = Math.floor(sec / 60);
        let minmin = Math.floor(min % 60);
        let min3 = (parseInt(time[nowstation])-parseInt(time[nowstation-1]))-(parseInt(Math.floor(sec / 60))-parseInt(time[nowstation-1]))-1;
        let hour = Math.floor(min / 60);
        secsec = addZero(secsec);
        sec4 = addZero(sec3)
        min2 = addZero(minmin);
        min4 = addZero(min3);
        hour = addZero(hour);
        if(min+departuretime>=time[nowstation]){
            nowstation++
            coffeecount++
            let b = document.getElementById("bell");
            let d = document.getElementById("door");
            b.play();
            b.addEventListener("ended", function(){
                d.play();
            }, false);
            changenext();
            if(waittime==1){
                waittime=0;
                document.getElementById("study").innerHTML="勉強"
                document.getElementById("study").style.color="#ff0000"
            }
            if(coffeecount>stu){
                coffeecount=0;
                waittime=1;
                document.getElementById("study").innerHTML="休憩"
                document.getElementById("study").style.color="#00B2E5"
            }
        }
        if((min+departuretime)+1>=time[nowstation] && secsec>30){
            document.getElementById("next").innerHTML="まもなく"
        }else{
            document.getElementById("next").innerHTML="次は"
        }
        let numbering=47-nowstation
        numbering=addZero(numbering);
        section=station[nowstation]+"(JK-"+numbering+")"
        document.getElementById("nowstation").innerHTML=section;
        document.getElementById("nowtime").innerHTML=""+hour+":"+min2+":"+secsec+"."+point2;
        if(min>=alltime){
            clearInterval(stationtimer);
            alert("終了です。")
        }
    }

今後の展望

  • 様々な路線に対応
  • 現実のトレインビジョンに似せる
  • コードをもうちょっと綺麗に
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む