- 投稿日:2019-12-09T22:33:33+09:00
年末まで毎日webサイトを作り続ける大学生 〜52日目 JavaScriptで神経衰弱ゲームを作る〜
はじめに
こんにちは!@70days_jsです。
今日は神経衰弱を作りました。
全部クリアすると、なんと!
最後にとっておきの画像を見ることができます!
(大声では言えないですが、思わず興奮してしまう画像です...)ぜひやってみてください。
ちなみにバグもありまして、素早く連続でクリックすると何枚もカードが開けてしまうのでご了承ください。直す時間がありませんでした。
今日は52日目。(2019/12/9)
よろしくお願いします。サイトURL
https://sin2cos21.github.io/day52.html
やったこと
ほぼ全てJavaScriptで作りました。一部cssのアニメーションも使っています。
のでhtmlは何もなし↓<body></body>
JavaScript長いですが一応全て載せます↓
window.onload = function() { createCardWrapper(); //wrapperを作る createCard(); //cardを作る }; let divWrapper; //一番大枠のdiv let countDisplay; let countDisplaySpan = document.getElementById("countDisplaySpan"); let card = [ { 0: "" }, { 1: "" }, { 2: "" }, { 3: "" }, { 4: "" }, { 5: "" }, { 6: "" }, { 7: "" }, { 8: "" }, { 9: "" }, { 10: "" }, { 11: "" }, { 12: "" }, { 13: "" }, { 14: "" }, { 15: "" } ]; //それぞれのcardにつけるid let image = ["1", "2", "3", "4", "5", "6", "7", "8"]; //cardの画像名 let imageNumber = 0; let beforeCard = ""; //前にクリックしたcard let id; //クリックしたcardのid(=key) let countClick = 2; //1回目か2回目かの判断 let goal = 0; //全て当てたかどうかの判断 function clicked(e) { open(e); //cardクリック時のモーション successOrFailure(e); } //cardクリック時のモーション 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"); }); } function successOrFailure(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() { let before = 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配列の順番をシャッフルする 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; } } //一番大枠のwrapperを作成する関数 function createCardWrapper() { 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枚作る関数 function createCard() { shuffle(); //画像をシャッフルする for (var i = 0; i < card.length; i++) { let div = document.createElement("div"); let key = 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); } //画像の表示を遅らせるための関数 function delayImageDisplay(delay) { return new Promise(function(resolve) { setTimeout(resolve, delay); }); } 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); }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; } @keyframes rotate { 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画像は国宝級の画像を用意しました。
皆さんもぜひ試してみてください!(アプリでは全て見れます)↓
感想
ちょっと今日は説明が意味不明すぎることになっていると思います。
申し訳ありません。というのも、手当たり次第に作っていたら色々と複雑になってしまい、全てを言語化していたら膨大な量になってしまうと判断したからです。
今後は最初にきちんと設計して、なるべくシンプルなコードを書けるように尽力します最後まで読んでいただきありがとうございます。明日も投稿しますのでよろしくお願いします。
参考
- アイコン素材ダウンロードサイト「icooon-mono」 | 商用利用可能なアイコン素材が無料(フリー)ダウンロードできるサイト | 6000個以上のアイコン素材を無料でダウンロードできるサイト ICOOON MONO
- パブリックドメインQ:著作権フリー画像素材集
画像を使用させていただきました。
- 投稿日:2019-12-09T21:20:57+09:00
初心者によるプログラミング学習ログ 179日目
100日チャレンジの179日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
179日目は
おはようございます
— ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) December 8, 2019
179日目
webサイトコーディング課題
フッター作成(途中)
テンションあがらずあんまりできなかった#100DaysOfCode #早起きチャレンジ#駆け出しエンジニアと繋がりたい
- 投稿日:2019-12-09T20:52:16+09:00
技術ポートフォリオを作った話
つい先月,自分の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のサービスである.
setting
にgithub pages
の項目があるのでそこでソースをマスターブランチに登録するだけである.とりあえずhello worldとでも書いたindex.html
を用意して公開すればいい.2.サンプルページを探してくる
結構フリーでHTMLとCSSのソースは落ちている.特に
template free engineer portfolio
とでも検索すれば,ごまんとフリーテンプレートが見つかる.私は以下のサイトから見つけてきた.(確か.)
50 free portfolio website templates 20193.自分仕様に変更する
後はダウンロードしたデータを自分仕様にカスタマイズするだけだ.先のテンプレートサイト等には結構な量のデータがあるので,私のような初心者エンジニアにはいらない部分が多すぎる.なので「いらない部分を削る」作業が必要になる.これには,どこからどこまで削っても問題なく動作するのか判断するために,HTMLの構造を理解している必要がある.CSSは色のテイストや配置などを変えたくなってから触る方が楽なのでとりあえず置いておいて,
HTML
→CSS
の順でカスタマイズするのがおすすめ.おめでとう!
ここまでのプロセスでやっと技術ポートフォリオをつくることができる.新しいことに取り組むことがあれば,どんどん追加して素晴らしいポートフォリオにしよう.
参考サイト
- 投稿日:2019-12-09T20:31:43+09:00
jQueryプラグインの実践
jQueryプラグインの実践をしてみた
こんにちは。ちょっとずつ学習したことを実践して投稿します。
やったこと
jQueryとjavaScriptを使って、
1. 画像をクリックしたら、そのフォントサイズを表示する。
2. ボタンをクリックしたらテキストを取得し表示するコード
部分的にコードを抜粋します。
index.htmlに画像などいろいろと要素を埋め込んでいきます。
jquery.showsize.jsの方へ画像をクリックした際の動作を埋め込んでいき、外部ファイルとして取得します。index.html<button type="button" name="button"> <p><img src="img/hoge.jpg"></p> <div id="cat1-button"><p id="text-a">click</p></div> </button> <button type="button" name="button"> <p><img src="img/hogehoge.jpg"></p> <div id="cat2-button"><p id="text-b">click</p></div> </button> <button type="button" name="button"> <p><img src="img/hogehogehoge.jpg"></p> <div id="cat3-button"><p id="text-c">click</p></div> </button> <button type="button" name="button"> <p><img src="img/hogehogehogehoge.jpg" data-size="30"></p> <div id="cat4-button"><p id="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) { var elements = this; elements.each(function() { var opts = $.extend({}, $.fn.showsize.defaults, options, $(this).data()); $(this).click(function() { var msg = $(this).width() + ' x ' + $(this).height(); $(this).wrap('<div style="position:relative;"></div>'); var div = $('<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); }); }); return this; }; function getRandomColor() { var colors = ['white', 'skyblue', 'orange', 'green']; return colors[Math.floor(Math.random() * colors.length)]; } $.fn.showsize.defaults = { size: 10, opacity: 0.9 }; })(jQuery);後記
複数のscriptが続く際には、{}で括るという初歩的なことが大事だと痛感しました。
このコードをサンプルとしてご自由にご利用ください。
- 投稿日:2019-12-09T20:20:23+09:00
はじめてぶらうざののべるげーむをつくってみたの!
はじめてぶらうざののべるげーむをつくってみたの!
自分でノベルゲーを作りたくなったので、モチベ維持のためにもQiita記事にしました。
ゆくゆくは簡単にブラウザノベルゲームを作れるソフトでも作りたいなと思ってるので、その下調べ的ななにがしですね。Qiita記事は初心者なので、なんか書いた方がいいこととかあれば教えてくだせぇ。
それではさっそく行きましょう。Chapter 0.使用言語
- HTML
- CSS
- JavaScript(JQuery)
Chapter 1.とりあえずタイトル画面つくるかのぅ…。
タイトル画面がないと始まりません。
1.仮でとりあえず作っていきます。
html<body> <h1>ノベルゲーム!</h1> <a href="">続きから</a> <a href="">最初から</a> <a href="">環境設定</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にしました。
この時点では、h1要素とa要素の中身は中央寄せになりましたが、a要素自体は左に寄っています。これを真ん中に持ってくるためにdisplay:flex;
を召喚します。html<div id="felxcontainer"> <h1>ノベルゲーム!</h1> <a href="">続きから</a> <a href="">最初から</a> <a href="">環境設定</a> </div>css#flexcontainer{ display:flex; flex-flow: column nowrap; align-items:center; position:absolute; top:0;bottom:0;left:0;right:0; }3.背景がなんか寂しいなぁ…。
というわけでネットのフリー画像を背景に指定。
cssbody{ background:url("image/TopImage.jpg"); margin:0; padding:0; position:absolute; top:0; bottom:0; left:0; right:0; }全体的に上に寄っているので、h1とaの親要素(#flexcontainer)のcssに、
justify-content:center;
を追加します。すると以下の通り全体が真ん中に来ます。
4.あとはこまごま調整して…
html<body> <div id="flexcontainer"> <h1>ノベルゲーム!</h1> <div> <a href="">続きから</a> <a href="">最初から</a> <a href="">環境設定</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: column nowrap; align-items:center; justify-content: center; position:absolute; top:0;bottom:0;left:0;right:0; } #flexcontainer div{ border:2px solid white; 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(ここのフリー画像を使いました。)
- 投稿日:2019-12-09T19:30:41+09:00
Rails6 数値入力時にtypeをnumberにしたのに数値として扱われず困った話
目的
- 勉強の実施時間を記録するwebアプリ作成の際に数値のinputで詰まり、コミュニティの方に助けていただいた話をまとめる
- そもそもセオリーを理解できていなかったので二度とこんなことない様にまとめる。
.to_i
を使って数値に変換できることはなんとなく知識としてあったが定着していなかったのでまとめる。目標
- すでにDBに格納されている数値に入力数値を足してDBに格納する。
- 不動小数点や符号などはとりあえず考えず前述の目標をクリアする。
結論
- 教えていただいた現役エンジニアさんのお言葉「入力値はtype指定してもStringになってしまうので受け取った側で型を指定して変換する」
問題のコード
下記に問題のコードの一部を抜粋する。
コントローラ
def update @post = Post.find_by(id: params[:id]) @post.study_time = @post.study_time + params[:study_time] @post.save redirect_to("/posts/#{@post.id}") endビュー
<%= form_tag("/posts/#{@post.id}/update") do %> <p>今日つみかさねた時間</p> <input type="number" name="study_time"> <input type="submit" value="今日のつみかさね登録"> <% end %>詰まったところまでの概要
前述の問題のコードにて「今日のつみかさね登録」ボタンを押したところ下記のエラーが出た。
no implicit conversion of integer into stringエラーの内容から足そうとしている数値の型があっていないことがわかった。
筆者はビューファイルの
input
でtype="number"
を指定して入力型を数値にしようと試みたが同じエラーが出た。解決しようと試みたがいろいろ試してくうちに混乱してしまった。
解決方法
- コントローラで受け取った値の型を数値に変換すことにより問題は解決した。
正常動作したコード
下記に教えていただいた内容を元に修正を行なったコードを記載する。
コントローラ
def update @post = Post.find_by(id: params[:id]) @post.study_time = @post.study_time + params[:study_time].to_i @post.save redirect_to("/posts/#{@post.id}") endビュー
<%= form_tag("/posts/#{@post.id}/update") do %> <p>今日つみかさねた時間</p> <!-- type="number"だと0~9までの入力しか受け付けられないためおって修正が必要 --> <input type="number" name="study_time"> <input type="submit" value="今日のつみかさね登録"> <% end %>反省
.to_i
で数値に変換できることは知ってはいたが使いどころが理解できてなかった。- そもそもセオリーを理解できていなかった。
- 今考えると諦めなければ自己解決できたかもしれない。
よかったこと
- エラー文をコピペで解決することをしなかった。
- エラー文から問題箇所を特定することができた。
- 投稿日:2019-12-09T16:45:57+09:00
CSSサブグリッドで真のフレキシブルなレイアウトを実現する方法
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;
を適用することで、以下の画像のように対象の要素はグリッドコンテナーとして、グリッドコンテナーの子要素はグリッドアイテムとして扱われます。
<ul style="display: grid;"> <!-- グリッドコンテナー --> <li>ぺんぎん</li> <!-- グリッドアイテム --> <li>あざらし</li> <!-- グリッドアイテム --> <li>らっこ</li> <!-- グリッドアイテム --> </ul>CSS Gridの問題点
CSS Gridを用いることで、グリッドアイテムの高さを柔軟に揃えることが可能となりました。
では、我々の戦いはGridの登場によって終わりを迎えたのでしょうか。そんなことはありません。グリッドアイテムの中の要素に目を向けるとどうでしょう。
グリッドアイテムの中には画像やテキスト等の複数の要素を設ける必要があります。これらのテキストはコンテンツによって変化するため、実装時には様々な高さへ変化することを想定しなくてはいけません。しかしながら、グリッドアイテムは以下の画像のように、中の要素の高さまでは揃えることができません。
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~ のみ対応しています。
Subgrid | Can I Use...より使い方
サンプル
(Firefox 71~で確認してみてください。)
実装方法
Subgridは以下のソースコードで対応することが可能です。
<ul class="gridContaienr"> <li class="gridItem"> <img src="https://via.placeholder.com/150" alt=""> <h3>タイトル</h3> <p>テキスト</p> <a href="http://example.com/">リンク</a> </li> <li class="gridItem"> <img src="https://via.placeholder.com/150" alt=""> <h3>タイトル</h3> <p>テキスト</p> <a href="http://example.com/">リンク</a> </li> <li class="gridItem"> <img src="https://via.placeholder.com/150" alt=""> <h3>タイトル</h3> <p>テキスト</p> <a href="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: span 4; grid-template-rows: auto auto 1fr auto; /* fallback for non-supported browsers */ grid-template-rows: subgrid; }まずは
.gridItem
へdisplay: grid;
を指定することでグリッドコンテナーとして扱う必要があります。
同時に、grid-template-rows: subgrid;
を指定することで、グリッドコンテナーをサブグリッド化することができます。こちらの例ではSubgridに対応していないブラウザ用のフォールバックとして、
grid-template-rows: auto auto 1fr auto;
を指定しています。
可変させる要素と固定させる要素を明示することで、Subgridに対応していないブラウザでも最低限のレイアウトを担保できるので、未サポートブラウザが多い現在はこちらの記述も必須でしょう。終わりに
CSS SubgridはFlexやGridだけでは実現できなかったレイアウトを簡潔に実現できる力を秘めていると考えられます。
現在はFirefoxのみが対応していますが、今後より多くのメジャーなブラウザへの実装され、ユーザーへ提供できるようになることを願ってやみません。参考サイト
- 投稿日:2019-12-09T16:08:01+09:00
CSSだけで動的サイトを作れるらしい!!
はじめに
最近まで深層学習の技術ブログを書いていたが、心機一転して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関数で要素に傾斜をつける変形を行うことができます。
- 投稿日:2019-12-09T15:40:16+09:00
Sortable.jsを使ってスパイダーソリティアを作ってみた
はじめに
現在SIerからWebエンジニアへの転職活動中で、ポートフォリオの一つとして
私の好きなゲームであるスパイダーソリティアをつくってみることにしました。
(スパイダーソリティアのルールはこちらから)ソース:Git Repo
プレイ:こちらから
※レスポンシブ対応はしていません(PCのみ)イメージ
終わりに
- 作成期間は約1か月ほどかかりました
- アルゴリズムや、一からのモノ作りを学ぶことができました
- SortableJSは結構いろいろな動作をさせることができました
途中ほんとうに挫折しかけましたがなんとか完成させることができたのでとても良かったです!
<使用技術>
HTML/CSS/JavaScript/SortableJs/Bootstrap/JQuery etc<参考にしたサイト>
【jQueryUIを使わずにドラッグ&ドロップを実装したい】Javascriptライブラリ「Sortable」を使ってみた
- 投稿日:2019-12-09T14:29:28+09:00
HTML CSS Flexboxとは
要素を並べるのに
float: left;
使ってるけど、他にも並べる方法ないかなあ参考サイト→https://www.webcreatorbox.com/tech/css-flexbox-cheat-sheet#flexbox1
随時更新しますFlexboxを使ってみよう
FlexboxとはFlexible Box Layout Moduleの略。左から順に並べられるのは勿論、右からや下からなど自由に要素をレイアウト出来る。
基本
flex_box01.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ブロックとインライン</title> <link rel="stylesheet" href="css/flex_box01.css"> </head> <body> <div class="container01"> <div class="item"> アイテム 1 </div> <div class="item"> アイテム 2 </div> <div class="item"> アイテム 3 </div> <div class="item"> アイテム 4 </div> </div> </body> </html>flex_box01.css.container01 { display: flex; } .item { margin: 10px 10px; padding: 2px 4px; background: #f8dcdc; }
display: flex;
を親要素に適用し、子要素が横に並んだ。Flexboxで親要素に指定するプロパティ
htmlは上と同じ。
flex-direction: row;
flex_box02.css.container01 { display: flex; flex-direction: row; } .item { ~省略~ }flex-direction: row-reserve;
flex_box03.css.container01 { display: flex; flex-direction: row-reverse; } .item { ~省略~ }flex-direction: column;
flex_box04.css.container01 { display: flex; flex-direction: column; } .item { ~省略~ }flex-direction: column-reverse;
flex_box05.css.container01 { display: flex; flex-direction: column-reverse; } .item { ~省略~ }flex-wrap: nowrap;
説明のために数を増やした
flex_box02.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ブロックとインライン</title> <link rel="stylesheet" href="css/flex_box.css"> </head> <body> <div class="container02"> <div class="item"> アイテム 1 </div> <div class="item"> アイテム 2 </div> <div class="item"> アイテム 3 </div> <div class="item"> アイテム 4 </div> <div class="item"> アイテム 5 </div> <div class="item"> アイテム 6 </div> <div class="item"> アイテム 7 </div> <div class="item"> アイテム 8 </div> <div class="item"> アイテム 9 </div> <div class="item"> アイテム 10 </div> </div> </body> </html>flex_box06.cssbody { ~省略~ } .container02 { margin: 10px auto; display: flex; flex-wrap: nowrap; } .item { ~省略~ }flex-wrap: wrap;
flex_box06.cssbody { ~省略~ } .container02 { margin: 10px auto; display: flex; flex-wrap: wrap; } .item { ~省略~ }flex-wrap: wrap-reverse;
flex_box07.cssbody { ~省略~ } .container02 { margin: 10px auto; display: flex; flex-wrap: wrap-reverse; } .item { ~省略~ }flex-flow: ;
flex_box08.css.container02 { margin: 10px auto; display: flex; flex-flow: row-reverse nowrap; }
flex-direction
とflex-wrap
を一行で指定できるプロパティ。justify-content: flex-start;
flex_box09.css.container02 { margin: 10px auto; display: flex; justify-content: flex-start; }
10個だと分かりにくかったので5個にした。親要素に空いているスペースがあるとき、子要素を水平方向のどの位置に置くか指定。
flex-start
は左揃えになる。justify-content: flex-end;
flex_box10.css.container02 { margin: 10px auto; display: flex; justify-content: flex-end; }justify-content: flex-center;
flex_box11.css.container02 { margin: 10px auto; display: flex; justify-content: flex-center; }justify-content: space-between;
flex_box12.css.container02 { margin: 10px auto; display: flex; justify-content: space-between; }
- 投稿日:2019-12-09T13:09:47+09:00
box-shadowで月の表現
最終成果物
これです。
ぽいですね。
これがbox-shadowプロパティで実現できます。実装
土台になるhtmlの用意
さっくりと。
moon.html<!DOCTYPE html> <html lang ="ja"> <head> <link rel="stylesheet" href="../css/moon.css"> </head> <body> <main class="stage"> <div class="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: solid 5px #6e5c60; border-radius: 30px; box-sizing: border-box; opacity: 0.3; } /** * moon */ .moon { width: 500px; height: 500px; border-radius: 100%; animation: anime 5s linear infinite; } @keyframes anime{ from{ box-shadow: none; } to{ box-shadow: 500px -200px 0 0 rgb(254, 228, 137) inset; } }ちょっとだけ解説
実際のイメージとは逆かもですが、黄色の明るい部分がbox-shadowで表現されている部分です。
keyframesで定義されている通り、影がない状態から影がある状態にアニメーションさせています。
円形に別のオブジェクトを重ねようとするとどうしても線形な変化になってしまうので、自身に影をつけることで変化させます。
当然外側に影をつけても月にはならないので内側に変化させるためにinsetをbox-shadowにつけるのを忘れずに。まとめ
box-shadowを内側につけるのは何かと使う場面がありそうですね。
意識していないと忘れてしまいそうなプロパティなのでたまに使ってあげましょう。
- 投稿日:2019-12-09T10:51:57+09:00
初学者が手っ取り早くコーディング練習する方法
こんにちは、たか(@HighHawk5)です。
普通はローカル(自分のパソコン)に開発環境を用意してコーディングしますが、面倒だったりできない場合に便利なのがクラウドIDE。ブラウザ上で簡単にコーディング&表示確認ができます。
今回は数あるクラウドIDEのなかでも一番ライトに使えるCODEPENをご紹介します。
メリット
・開発環境の構築が不要
・色々なエンジニアの作品を参考にできるこれは私のpenですが、このようにコーディング&表示確認が一画面でできて便利ですよね!
右上のCODEPENアイコンから本サイトに移動し、メニューの「Fork」をクリックすると、私の作品をあなたのワークスペースにコピーしてコーディングすることもできます。模写がボタン一発で!Vue.jsはこちらのサンプルなんてどうでしょう?
https://codepen.io/JavaScriptJunkie/pen/YzzNGeRコーディングの上達方法は、見本のコードを模写してイジり倒すこと!
では、より良いエンジニアライフを!
おしまい
- 投稿日:2019-12-09T10:51:57+09:00
初学者が簡単にコーディング練習する方法
こんにちは、たか(@HighHawk5)です。
普通はローカル(自分のパソコン)に開発環境を用意してコーディングしますが、面倒だったりできない場合に便利なのがクラウドIDE。ブラウザ上で簡単にコーディング&表示確認ができます。
今回は数あるクラウドIDEのなかでも一番ライトに使えるCODEPENをご紹介します。
メリット
・開発環境の構築が不要
・色々なエンジニアの作品を参考にできるこれは私のpenですが、このようにコーディング&表示確認が一画面でできて便利ですよね!
右上のCODEPENアイコンから本サイトに移動し、メニューの「Fork」をクリックすると、私の作品をあなたのワークスペースにコピーしてコーディングすることもできます。模写がボタン一発で!Vue.jsはこちらのサンプルなんていかがでしょう?
コーディングの上達方法は、見本のコードを模写してイジり倒すこと!
では、より良いエンジニアライフを!
おしまい
- 投稿日:2019-12-09T01:01:19+09:00
FloatとFlexboxについて
はじめに
中一日でAdventcalendarの日がまわってQiita!
今回は、自分がいまいち理解できなかったFloatとFlexboxの違いについてまとめてみました。本題
みなさんは、要素を横並びにするときに何を使っていますか??
FloatやFlexbox,FloatにFlexboxなどなどさまざまな方法があると思います。
ということで今回は、FloatとFlexboxって、なにがちがうの?どっちの方を使ったほうがいいのかという2つの観点に目を向けて記事を書いていこうと思います。今回はFloat・Flexboxを用いて下記のような表示をさせるためにコードを記述していきます。
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
- .clearfix::after{}により、回り込みを防ぐ
- `::after` セレクタ要素の直後にスタイルや要素を追加するもの
- `content: "";` floatされた要素の親要素の直後に空白の要素を挿入
- `display: block;`: contentプロパティによって挿入された空白を横いっぱいに伸ばし、壁のようにする。
- `clear:both;`: displayプロパティによって作成れた壁にfloatの回り込みを解除するための機能を与える。
- `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を使って楽にコードを書いてみてはいかがでしょうか。参考資料