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

【javascript】ハンバーガーメニュー作成(メニュー外のクリック動作)

目標

Xボタンだけでなく、右側の表示領域をクリックしても、
ハンバーガーメニューが閉じるようにします。
ハンバーガーメニュー.gif

開発環境

ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina

前提

【Javascript】ハンバーガーメニュー作成(左、上、右から表示)
今回は上記記事の補足になります。

実際のコード

html
<div id="box"></div> <!-- 追加 -->
<nav id="nav">
  <ul>
    <li><a href="#">リンク1</a></li>
    <li><a href="#">リンク2</a></li>
    <li><a href="#">リンク3</a></li>
  </ul>
</nav>
<div id="hamburger">
  <span class="inner_line" id="line1"></span>
  <span class="inner_line" id="line2"></span>
  <span class="inner_line" id="line3"></span>
</div>

<style>
body{
   background-color: rgba(0,0,0,0.2);
 }

#nav{
  position: absolute;
  height: 100vh;
  width: 40%;
  left: -40%;
  top: 0;
  background: #ffffff;
  transition: .7s;
}
#nav ul{
  padding-top: 80px;
}
#nav ul li{
  list-style-type: none;
}
#hamburger {
  display: none;
  position: absolute;
  top: 20px;
  left: 30px;
  width: 50px;
  height: 44px;
  transition: 1s;
}
.inner_line {
  display: block;
  position: absolute;
  left: 0;
  width: 50px;
  height: 3px;
  background-color: #000000;
  transition: 1s;
  border-radius: 4px;
}
#line1 {
  top: 0;
}
#line2 {
  top: 20px;
}
#line3 {
  bottom: 0px;
}

.in{
  transform: translateX(100%);
}
.line_1,.line_2,.line_3{
  background: #000000;
}
.line_1 {
  transform: translateY(20px) rotate(-45deg);
  top: 0;
}
.line_2 {
  opacity: 0;
}
.line_3 {
  transform: translateY(-20px) rotate(45deg);
  bottom: 0;
}

/* ここから*/

#box{
  position: absolute;
  height: 100vh;
  width: 100%;
  left: -100%;
  top: 0;
  background: rgba(0,0,0,0.8);
}
.back{
  transform: translateX(100%);
}

/* ここまで追加*/


@media (max-width: 1200px) {
  #hamburger {
    display: block;
  }
}
</style>

<script>
  function hamburger(){
    document.getElementById('line1').classList.toggle('line_1');
    document.getElementById('line2').classList.toggle('line_2');
    document.getElementById('line3').classList.toggle('line_3');
    document.getElementById('nav').classList.toggle('in');
    document.getElementById('box').classList.toggle('back'); // 追加
  };
  document.getElementById('hamburger').addEventListener('click',function(){
    hamburger();
  });

  // ここから
  document.getElementById('box').addEventListener('click',function(){
    hamburger();
  });
// ここまで追加
</script>

追加項目

追加箇所-html
<div id="box"></div>
追加箇所-css
#box{
  position: absolute;
  height: 100vh;
  width: 100%;
  left: -100%;
  top: 0;
  background: rgba(0,0,0,0.8);
}
.back{
  transform: translateX(100%);
}
追加箇所-js
document.getElementById('box').classList.toggle('back');

document.getElementById('box').addEventListener('click',function(){
  hamburger();
});

まとめ

方法としては前提記事同様、画面外に表示させておき、
classList.toggle('back')でbackクラスを付与して表示させています。
アニメーションもつけることはできますが、
一緒に出てくると少し違和感があったので、アニメーションはつけていません。

もしスクロールアウトしてもハンバーガーメニューを表示させたい場合は、
#nav,#hamburger,#boxposition: absolute;position: fixed;
に変更すれば可能です。

またtwitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら https://twitter.com/japwork

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

はじめてのCSS設計の記録【決定編】

はじめに

この記事ははじめてのCSS設計の記録【検討編】からの続きとなっています。
初めてCSSの設計を行った記録になります。改善できる部分はまだまだあるかと思いますので、都度振り返りを行い定期的にアップデートをしていきたいと思います。

はじめてのCSS設計

基本設計:PRECSS
命名規則:MindBEMding

MindBEMding(マインドベムディング)とは

BEMをCSSのクラス名に適用するために作られた規則のことです。CSSの話をしている時はMindBEMdingがBEMと呼ばれることが多いそうです。つまり、「CSSはBEMを使おう」→「CSSのクラス名はBEMのMindBEMdingに従って命名しよう」と変換することができます。

CSSのカテゴライズ

  1. ベース
  2. レイアウト
  3. モジュール
  4. ユニーク
  5. ヘルパー
  6. プログラム

基本的にはPRECSSの設計をそのまま使用しています。各グループをそれぞれファイルに分けて管理しています。公式との差異は①モジュールに接頭辞をつけないこと、②モジュールをブロックとエレメントにファイル単位で分割しないことの2点です。

1. ベース

配置内容:HTML要素、標準スタイル、リセットCSSなど
接頭辞:なし

ベースにはプロジェクトの標準となるスタイルや、リセットCSSを配置します。ほとんどをHTML要素に対してスタイリングしています。今回、リセットCSSにはブラウザ間の統一は図るけど要素の役割の全てを壊したくないという考えからNormalize.cssを適用しました。
更に細かく分けて管理したい場合、PRECSSではオリジナルのグループを作成することができる柔軟な設計になっているので、リセットCSSを新規のグループに分けて配置するのがいいでしょう。

2. レイアウト

配置内容:ヘッダー、メインエリアなどの大きなレイアウトを形成する要素
接頭辞:ly_

レイアウトにはヘッダー、メインエリア、フッターなどの要素を配置します。メインエリアの中が2カラムであれば、更にコンテンツエリアとサイドエリアなどに分けていきます。画面ごとにレイアウトが異なる場合はその都度枠組みとなるスタイルを追加していく必要があるでしょう。
他の開発者がHTMLを見た時、lyの接頭辞がついているクラス名をみて、このクラスがレイアウトを形成しているから自分が今から開発しようとしている画面にも適用しよう、という風に判別がつきやすくなっています。

3. モジュール

配置内容:再利用性のあるコンテンツ
接頭辞:なし

モジュールには再利用性のあるスタイルを配置します。モジュールとは、コンポーネントとも言い換えることができ、特定のエリアに依存せずどこでも使用が可能なものとなっています。特定のエリアに依存せず、とはモジュールが他のスタイルが適用されている要素下でもデザインの崩れがない状態を指します。
PRECSSのモジュールにはブロックモジュールエレメントモジュールに分けられていますが、BEMを使用したいと思い今回は統一しています。
更に、接頭辞がありませんが、これは接頭辞なしのクラス名はモジュールグループと判断することができ、あまりクラス名が長くならないようにと考え、つけない方針にしました。

モジュールにはBEMの命名規則を適用します。
BEMとはBlockElementModifierの略で、それぞれ以下のように定義されています。

Block:どこでも使い回せるパーツ
Element:Blockの構成要素、Blockの中でしか機能しないもの
Modifier:BlockやElementの修飾を定義するもの

記法は以下のようになっており、Elementはアンダースコア2つ(__)、Modifierはハイフン2つ(--)で連結するようにします。

block
block__element
block__element--modifier
block--modifier
block--modifier__element

エレメントの下層にエレメントが来るパターンもあるかと思いますが、その場合もエレメントを2つ繋げずに、block__elementの記法で問題ありません。ブロックが一意になっている想定なので、エレメントを重ねて命名する必要がないためです。
ElementやModifierを定義するとき必ず先頭にBlockになりクラス名が長くなりがちですが、これはどのブロックに対してなのかがわかるみだりに影響範囲を広げないといった目的があります。BEMを適用する際、後述するSassを使用することで効率よく開発することができますのでぜひ取り入れましょう。

4. ユニーク

配置内容:ある特定の場所でしか使用していないスタイル
接頭辞:un_

特定の場所でしか使用していないので、影響範囲がなく後からの修正が容易です。ただ、あまり乱用すると再利用性がなくなってしまうので、ユニークに配置するときはモジュールに配置できないか一旦検討してみるのがいいと思います。
ユニークグループに配置したスタイルには、どの画面で使用しているかそれぞれコメントを残すようにします。

5. ヘルパー

配置内容:単一のスタイルなど
接頭辞:hp_

marginやpaddingなど、ある部分だけを調節したいとなった場合に適用するスタイルを配置します。BootStrapのmt-0のようなクラスを定義するイメージです。

6. プログラム

配置内容:JSなどでHTML要素を取得する際にセレクタとなるクラス、状態を管理するクラスなど
接頭辞:js_ または is_

JSで要素に対して何か操作をする際に、接頭辞の「js_」を付けたクラスをセレクタとして扱います。また、状態の管理は接頭辞「is_」を使用し、例えばis_activeというクラスにdisplay: blockなどを当てる、といったようにスタイルを適用します。

開発手順

【使用するもの】
  • Fractal:スタイルガイドジェネレーターの1つ。プロジェクト内のモジュールを一元管理することができる(公式サイト
  • Sass(LibSass):CSSメタ言語。今回はnode-sassライブラリでSassを使用する(公式サイト
  • gulp:様々な処理を自動化するツール。Sassのコンパイル時に使用する(公式サイト

開発において使用するツールや言語です。
詳しい説明はそれぞれ公式サイトをご確認ください。

【事前準備】
  • fractal.config.jsがあるディレクトリでfractal start --sync
    →command not foundの場合
    • ../node_module/.bin/fractal start --sync
      または
    • npm i -g @frctl/fractal && fractal start --sync
  • gulpfile.jsがあるディレクトリでgulp sass:watch
     →command not foundの場合
    • node_module/.bin/gulp sass:watch
      または
    • npm i -g gulp-cli && gulp sass:watch

開発の前に2つのコマンドを入力しそれぞれ起動させておいてください。
fractalの方はfractal.config.jsを配置しているディレクトリ内のドキュメントやコンポーネントが保存された時、gulpの方はscssファイルが保存された時、それぞれ自動で更新がかかるようになっています。

【手順】
  1. Fractal上で利用できそうなモジュールを検索する
  2. 該当するモジュールが存在する場合はそのまま使用する
  3. 存在しない場合はFractalにモジュールのHTML側を作成する
  4. Sassでスタイリングする
  5. gulpでscssファイルをコンパイルする
  6. Fractalでモジュールの確認をする
  7. 実際のHTMLファイルにモジュールを適用する

1. Fractal上で利用できそうなモジュールを検索する

Fractalはスタイルガイドジェネレーターの1つです。スタイルガイドとはUIパーツやプロジェクト内のテーマをまとめておき、デザインの現物をそのまま確認することできるので、他の開発者が後から見た時に自分の使うべきクラスの見通しが立ちやすくなります。

まずはこのFractal上で、自分が利用したいモジュールがないか確認します。

image1.jpg

2. 該当するモジュールが存在する場合はそのまま使用する

利用できそうなモジュールがあった場合は、下のHTMLタブで適用されているクラス名を確認して実際のHTMLファイルに記述します。
例でいうと、標準ボタンモジュールを使用したいので、HTMLタブを見てbtnクラスを確認し、HTMLファイルに適用する、といった流れになります。

image2.jpg

3. 存在しない場合はFractalにモジュールのHTML側を作成する

利用できそうなモジュールがない場合は自分で新規作成する必要があります。このとき、後のこと考えてまずはFractal上でモジュールを作成していきます。

以下は、Fractalのディレクトリ構成となっています。
styleguideという名前でなくても問題ありません。

image3.jpg

components:各モジュールを配置します
docs:ドキュメントを配置します
fractal.config.js:fractalの設定ファイルです

componentsディレクトリにはHTML側を実装していきます。初期設定ではhandlebarsになっていますが、今回はpugを使用します。pugに変更する場合はfractal.config.jsで設定することができます。

componentsディレクトリには更にディレクトリを切っていますが、これはなくても問題ありません。一応大きなコンポーネントの括りで分けています。

以下の例では、Buttonのディレクトリの中にDefaultOutlineが存在しています。

image5.jpg

これはstyleguideディレクトリでbuttonディレクトリを切ったからではありません。ファイル名によってこうしたディレクトリ構成になっています。

image4.jpg

このように、button.pugとModifierであるbutton--outline.pugがありますが、Fractalではハイフン2つを連結させることで、そのファイルをデフォルトのモジュールに対しての変化系として認識させることができます。
ちょうどBEMのModifierと同じ命名方法だったのでそのまま使用することにしました。

長くなりましたが、最後にbutton.pugの中身を見てみましょう。

button.pug
a.btn(href='#') 標準ボタン
hr
a.btn(href='#') テキストが長い場合は折り返される標準ボタン
hr
.btn divタグの標準ボタン

ボタンモジュールなのでとても単純なので、複合モジュールのようなエレメントがたくさん入れ子になっているものだともっと複雑なものになるかと思います。
今回button.pugとしては1行目のコードだけで十分だったのですが、念の為Modifierまではいかないけど、そのモジュールの変化型をまとめておきたいと思い、hrタグの線で区切って複数パターンを表示させています。

他の開発者がFractalを使ってモジュールを見た時、このHTML要素で.btnクラスを使用すれば画面に表示されているボタンが使用できることを認識でき、再利用されてコードの重複を抑えることに繋がります。

4. Sassでスタイリングする

先程のボタンモジュールには.btnクラスを当てていました。このクラスに対してSassを使用してCSSの実装を行います。

なぜSassを使用するのかというと、PRECSSの6つのグループごとにファイルを分けたかったというのが理由になります。
CSSのままファイルを分けてしまうと、全てのファイルを1つずつ読み込む必要があり、微小ながらパフォーマンスに影響が出てしまいます。
Sassはコンパイルする時に複数のscssファイルを1つのCSSファイルにまとめることができ、読み込みも1つのファイルで済むことができます。

ディレクトリ構成は以下のようになっています。

image6.jpg

sassディレクトリ直下にstyle.scss_utiles.scsscategoriesディレクトリが配置されています。
categoriesにはPRECSSの6つのグループがファイルごとに分けられています。
style.scss以外のファイル名の先頭にアンダースコアが付いていますが、これはコンパイル時にファイルが生成されないようにするためです。では、そのファイルの中身はどのようにCSSとして出力されるかというと、style.scssの中身を見ることでわかります。

style.scss
@import 'categories/base';
@import 'categories/layout';
@import 'categories/module';
@import 'categories/unique';
@import 'categories/helper';
@import 'categories/program';

ファイル名にアンダースコアが付いたCSSファイルを出力しないscssファイルをパーシャルファイルと言いますが、このパーシャルファイルをstyle.scssで全てインポートすることで内容を一つにまとめ、style.cssとして出力することができます。
この時、インポートしたファイルの順番通りにCSSの中身も出力されるので、下の方にインポートしたscssファイル程優先度が高くなります。なので、自分は上書きが起きてほしいグループ程下にインポートするようにしているので、この辺は特にオリジナルグループを作成した時は、各自調整してみてください。

またまた長くなりましたが、最後に.btnのスタイリングですが、今回は_module.scssファイルに記述していきます。

_module.scss
.btn {
  display: inline-block;
  width: 300px;
  max-width: 100%;
  padding: 6px 10px;
  background-color:  #004E98;
  border: 2px solid transparent;
  border-radius: 5px;
  box-shadow: 0 3px 6px rgba(0, 0, 0, .16);
  color: #fff;
  font-size: 1.125rem;
  text-align: center;
  text-decoration: none;
  transition: .25s;

  &:focus,
  &:hover {
    background-color: #fff;
    border-color: currentColor;
    color: #004E98;
  }

  &--outline {
    background-color: #fff;
    border-color: #004E98;
    color: #004E98;
    &:focus,
    &:hover {
      background-color: #004E98;
      border-color: transparent;
      color: #fff;
    }
  }
}

5. gulpでscssファイルをコンパイルする

今回はgulpの設定で、ファイルを保存するとコンパイルしてくれるようにしています。
以下は出力されたCSSです。

style.css
.btn {
  display:inline-block;
  width:300px;
  max-width:100%;
  padding:6px 10px;
  background-color:#004e98;
  border:2px solid transparent;
  border-radius:5px;
  box-shadow:0 3px 6px rgba(0,0,0,.16);
  color:#fff;
  font-size:1.125rem;
  text-align:center;
  text-decoration:none;
  transition:.25s
}

.btn:focus, .btn:hover {
  background-color:#fff;
  border-color:currentColor;
  color:#004e98
}

.btn--outline {
  background-color:#fff;
  border-color:#004e98;
  color:#004e98
}

.btn--outline:focus, .btn--outline:hover {
  background-color:#004e98;
  border-color:transparent;
  color:#fff
}

.btnに対して.btn--outlineという枠線のみのボタンを表示させるModifierを用意しました。
SassはBEMととても相性が良く、scssの記述量が少なく済んでいるのが出力結果からわかるかと思います。

スタイリングが完了しましたので、後はFractalで実際のデザインを確認し、HTMLファイルへの方へ反映させて一連の流れが完了となります。

普通にCSSを書いて実装するより、時間が多少かかるかと思いますが、管理や他の開発者への共有のことを考えると時間をかけるべき工程だと思っています。

以上となります。
ありがとうございました。

参考

2018年の終わりに改めてgulpでsass(scss)をコンパイルする【決定版】
fractal のテンプレートをpugにする
Fractalを使ったスタイルガイドの作成(中級編)

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

はじめてのCSS設計の記録【検討編】

はじめに

自社のCSS設計を検討しました。
内容ははじめてのCSS設計の記録【決定編】に載せようと思いますが、そこに至った経緯や取り入れた様々な設計手法の概要をまとめましたので、興味があれば順番に読み進めてください。

今回はCSS設計完全ガイド ~詳細解説+実践的モジュール集を参考にさせて頂きました。とても良書でしたのでぜひ購入して読んでみてください。

CSS設計の8つの指標

CSS設計には目指すべき4つのゴールがあります。
他の言語にも言えることだと思いますが。

・予測できる
・再利用できる
・保守できる
・拡張できる

この「目指すべき4つのゴールが満たされる」==「よいCSSである」、ということになります。
そして、CSS設計の4つのゴールを実現するために8つの指標があり、BEMやSMACSSなどの設計手法では、8つの指標のいずれかに該当します。

下記の表は8つの指標とその指標を採用している設計手法(OOCSS, SMACSS, BEM, PRECSS)、自分たちのチームで採用・意識しているかの現状をまとめたものになります。

8つの指標 設計手法 評価 チームの現状
1.特性に応じてCSSを分類する SMACSS, PRECSS × 意識していない
2.HTMLとスタイリングが疎結合 SMACSS, BEM
HTML要素をセレクタに
している時がある
3.影響範囲が広すぎない SMACSS, BEM
PRECSS
重複が起きそうなclass名
を使用している時がある
4.特定のコンテキストに
依存していない
ALL × 影響範囲を絞るために
コンテキストに依存している
5.詳細度がみだりに高くない BEM × かなり詳細度が高い
6.クラス名から
影響範囲が想像できる
SMACSS, BEM
PRECSS
クラス名に画面名を含めたり
しているが全てではない
7.クラス名から
見た目・機能・役割が想像できる
BEM, PRECSS 想像できるものもあるが
全てではない
8.拡張しやすい OOCSS, SMACSS
PRECSS
× 基本的に自作のスタイルは
シングルクラス設計になっている

△の偶にできているところも、明確なルール決めをしているわけではないので開発者によってバラバラになってしまっています。現状、少なくとも「よいCSS」ではないことがわかります。
そこで、8つの指標を取り入れているCSSの設計手法を導入したいと考えています。

設計手法検討

導入するCSS設計を検討したいと思います。
現在、OOCSS単体で開発することは少なく、他の設計手法に思想が取り入れられているため、SMACSSとBEM、PRECSSの3つの手法で検討したいと思います。

ある程度学習した後に3つの手法を完全にではありませんが組み込んで、トライ&エラーで開発をしてみました。
以下の表は、3つの手法の完全に個人的な主観に基づいた比較なので、ご了承ください。

SMACSS BEM PRECSS
厳格性
柔軟性
学習コスト ×
ドキュメント

SMACSS(スマックス)

http://smacss.com/ja

【特徴】
* 拡張可能でモジュール的なCSS設計(Scalable and Modular Architecture for CSS)のこと
* CSSのコードを役割に応じて5つのカテゴリ分けしている
* 規則を厳格にするために、OOCSSやBEMの一部を取り入れたりすることもある

SMACSSはCSSのコードを役割に応じて、ベースレイアウトモジュールステートテーマというカテゴリに分けています。こうすることで管理がとてもしやすいです。

柔軟かつある程度の規約があるので、初めてCSS設計手法を取り入れたとしても簡単に書くことができ、統一感のあるコードになるかと思います。

しかし、特徴の最後にある通り、ある程度規模が大きくなってくると規則を厳格にする必要が生じ、他の設計手法を取り入れる方法が採用されるそうです。実際に自分もSMACSSだけど自由に書けすぎてしまうと思い、SMACSS+何かで検討したいと思いました。

BEM(ベム)

http://getbem.com/

【特徴】
* Block、Element、Modifierの略
* OOCSSのように基本的にはモジュールベースで実装する
* 他の設計手法に比べて厳格/強力である
* BEMはカバーする範囲がCSSに留まらず、学習コストが比較的高い

BEMはCSSだけでなくファイルの出力方法やファイル構成なども厳格に定められている手法で、学習コストが他の設計手法に比べ高いですがその分強力に働きます。

今までCSS設計を導入したことがない場合、初めてがBEMだともしかしたら難しいかもしれません。ただ、BEMの命名規則は比較的導入しやすいと感じました。厳格であり、一発でスタイルを適用させることができるのでパフォーマンス的にも良いです。

PRECSS(プレックス)

https://precss.io/ja/

【特徴】
* 接頭辞付きのCSS(prefixed CSS)
* CSSを役割に応じて6つのグループに分類し、それぞれに規則を設けている
* グループごとに2文字の接頭辞をクラス名に付けており、開発要件に合わせて独自のグループを作成することも可能
* 命名規則がどのグループのものかわかりやすく、ある程度柔軟かつ厳格に定義することができる

PRECSSは名前の通り、CSSを役割に応じて6つに分け、それぞれのグループのクラス名に2文字の接頭辞を付けるようにしています。こうすることで、そのクラスがどのようなスタイリングをするか想像しやすくなり、使いまわしたり管理しやすくなります。

また開発要件に合わせ、オリジナルのグループも作成することができるので、柔軟かつある程度のルール化ができるので、導入がしやすいと感じました。

OOCSS、SMACSS、BEMに強く影響を受けており、それぞれのいいトコ取りをしていて、他の設計手法に馴染みがある人も導入のハードルが低いと思います。

結論

「導入しやすいものをそれぞれ取り入れて組み合わせる」
それぞれの設計手法はCSS設計の4つのゴールを満たすために考えられてますので、どれか1つに決めて構築していくでももちろん良いと思いますが、かゆい所に届かなかったり、学習コストが高く他の開発メンバーの導入が難しかったり、という懸念もあります。
なので、それぞれの良い点、導入しやすい点を組み合わせたものを自分たちのCSS設計としたいと思います。
大事なのは、これが完成版ではないということで、定期的な振り返りを行いアップデートを重ねて、より自分たちに適したCSS設計を目指していきましょう。

次回:はじめてのCSS設計の記録【決定編】

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

CSSでポップアップを表示させる方法

こんにちは!!
今回は、CSSのアニメーションを使ってポップアップの表示を実装してみました
サイトに遷移したときに出てくるキャンペーンのクーポンなどはこうやって作れるのかと分かりました:slight_smile:

1.index.html内に記述

index.html
<div class="message">Hello!</div>

2.cssへの記述

styles.css
.message {
  width: 300px;
  height: 50px;
  border-radius: 4px;
  padding: 8px 16px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, .2);
  background: #0f35e2;
  color: #ddd;
  position: fixed;
  top: 32px;
  right: 32px;

image.png
このような画像を作ることが出来ました
この記述にアニメーションをつけることでフェードインさせていきます

3.アニメーションの記述

styles.css
@keyframes popup {
  0% {
    transform: translateY(20px);
    opacity: 0;
    animation-timing-function: ease-out;
  }
  20%, 80% {
    transform: none;
    opacity: 1;
  }
  100% {
    transform: translateY(20px);
    opacity: 0;
    pointer-events: none;
  }
}
styles.css
.message {
  width: 300px;
  height: 50px;
      :
  animation: popup 2s forwards; //ここの記述を足す
}

popup.gif

このようにフェードインさせることが出来ました!!
今後は、Javascriptを使い、スクロールしたときに発火させたりしたいなあと考えています!!

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

cssの@keyframesアニメーションでガタゴト進む車を実装する

完成版デモ

See the Pen ガタゴト進む車 by kuma-onigiri (@kuma-onigiri) on CodePen.

実装イメージ

アニメーションは@keyframesを使います
1、車の画像を配置する
2、斜めに動くアニメーションをつける
3、上下にガタゴト動くアニメーションをつける

車を用意する

Illustratorで作った車をつかいます
car.png

ベースのHTMLとCSS

index.html
            <div class="move-animation">
                <div class="gata-gata-animation">
                    <img class="car" src="車の画像のパス">
                </div>
            </div>
main.css
.car {
    width: 75px; /* 車のサイズは適当に幅75pxくらい */
}

@keyframesは、1つの要素に複数のアニメーションをつけることはできないので、2段構えでつけています。
上下に揺れる用のgata-gata-animationクラスをつけた要素を、さらに<div>で囲って、動くアニメーション用のmove-animationクラスをつけてあげるのがポイントです。

斜めに動くアニメーションをつける

main.css
.move-animation {
    transform: translate(250px, 0px);

    animation: move 16s linear infinite;
}
@keyframes move {
    to {
        transform: translate(0px, 250px);
    }
}

初期位置はtranslateで右に250pxくらいずらした状態にしておきます。
そこから左下に動いていくアニメーションをつけます。時間は適当に16秒くらいにしてます。

上下にガタゴトうごくアニメーションをつける

main.css
.gata-gata-animation {
    animation: gata-goto .3s infinite;
}
@keyframes gata-goto {
    20% {
        transform: translateY(-2px);
        animation-timing-function: cubic-bezier(0.4, 0, 1, 1.3);
    }
    25% {
        transform: translateY(0px);
    }
    55% {
        transform: translateY(-1px);
        animation-timing-function: cubic-bezier(0.4, 0, 1, 1.3);
    }
    60% {
        transform: translateY(0px);
    }
}

transformで上下に2回動くのを作り、それをinfiniteで延々と繰り返しています。
ちょっとバウンドする感じにしたいのでanimation-timing-functioncubic-bezier(0.4, 0, 1, 1.3)にしています。

ここはブラウザの開発者ツールで調整できるのですが、
左の赤丸のところのマークをクリックするとベジエ曲線のグラフが出てくるので、ハンドルを動かして好きな動きにできます。
右の赤丸のところを上に盛り上がるようにすると、ぼよんって感じの動きになります。
bezier.png

おわり

アニメーションを2段構えにするのがポイントでした。
これを応用すれば、ぴょんぴょん動くアニメーションとかもできますね。

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

【jQuery】【ancestry】を使用した、多階層ツリーメニューの実装

経緯

現在絶賛作成中のポートフォリオで、フリマアプリのラクマのような多階層ツリーメニューを実装したいと思い作成。振り返ってみればさほど難しくはなかったけれども、色々躓いたので記載しておこうと思います。

環境

ruby 2.6.5
Rails 6.0.3.2
haml使用

完成図

moving image
親のカテゴリー(第1階層)をクリックすると、子のカテゴリー(第2階層)のサブメニューが現れるという仕組み。

手順

1、ancestryの導入
2、HTMLで多階層の形を実装
3、jQuery(JavaScript)で、第1階層のカテゴリーをクリックすると、第2階層のサブメニューが表示されるイベントを記載する

※CSSは今回は記載しません、ごめんなさい

ancestryの導入

余談ですが、ancestryを導入しなくても、HTMLに記載すれば多階層ツリーメニューの実装自体は出来ます。只、第2階層のサブメニューのカテゴリをクリックして、そのカテゴリの商品一覧を表示させたいとなるとancestryを導入は必須になります。

余計な余談になりましたが、早速ancestryを導入していきましょう!

Gemfile.
#追記(一番下が好ましい)
gem 'ancestry'

記載が終了したら、
ターミナルで% bundle install して % rails s忘れずに行いましょう。


続いてcategoryモデルの作成です。

ターミナル.
$ rails g model category

この時点で、マイグレーションファイルは作成されていますので、
マイグレーションファイルを編集しましょう。

2020xxxxxxxx_create_categories.rb
class CreateCategories < ActiveRecord::Migration[6.0]
  def change
    create_table :categories do |t|
      t.string :name, null: false #これを追記

      t.timestamps
    end
  end
end

ターミナルでrails db:migrate

さらに、categoryモデルにancestryのカラムを追加したいのでターミナルで以下のコマンドを入力

ターミナル.
% rails g migration AddAncestryToCategory ancestry:string:index

ターミナルでrails db:migrate

続いて、seedにデータ作成をします。
詳しくはこちらの記事を見てみてください。
分かりやすく書いてくれている記事なので、親カテゴリー、子カテゴリーなどの意味が理解出来ると思います。
【フリマアプリ】ancestryを用いたseedデーター作成について

seeds.rb にデータを記載していくんですが、今回は僕が作ったものを貼り付けておきますので参考にして見てください。と言ってもメチャクチャ使い回しなんですけど・・・・
大事なのは、name:xxxxxのxxxxxの部分なので、ここの名前を実装したいものと、照らし合わせて変更してください。

db/seed.rb
# パーツ
lady = Category.create(name: "パーツ")
lady_1 = lady.children.create(name: "パーツすべて")
lady_2 = lady.children.create(name: "マフラー")
lady_3 = lady.children.create(name: "エンジン/冷却装置")
lady_4 = lady.children.create(name: "ホイール")
lady_5 = lady.children.create(name: "タイヤ")
lady_6 = lady.children.create(name: "ハンドル")
lady_7 = lady.children.create(name: "ブレーキ")
lady_8 = lady.children.create(name: "外装")
lady_9 = lady.children.create(name: "駆動系")
lady_10 = lady.children.create(name: "電装形")
lady_11 = lady.children.create(name: "その他")

# アクセサリ
men = Category.create(name: "アクセサリ")
men_1 = men.children.create(name: "アクセサリすべて")
men_2 = men.children.create(name: "バイクカバー")
men_3 = men.children.create(name: "ステッカー/デカール")
men_4 = men.children.create(name: "タンクバック")
men_5 = men.children.create(name: "サドルバッグ/サイドバック")
men_6 = men.children.create(name: "シートバック")
men_7 = men.children.create(name: "ツーリングネット/ロープ")
men_8 = men.children.create(name: "鍵/ロック")
men_9 = men.children.create(name: "エアバック")
men_10 = men.children.create(name: "ETC")
men_11 = men.children.create(name: "ナビ")
men_12 = men.children.create(name: "オーディオ")
men_13 = men.children.create(name: "その他")

# バイクウェア
baby_kids = Category.create(name: "バイクウェア")
baby_kids_1 = baby_kids.children.create(name: "バイクウェアすべて")
baby_kids_2 = baby_kids.children.create(name: "ヘルメット/シールド")
baby_kids_3 = baby_kids.children.create(name: "ゴーグル")
baby_kids_4 = baby_kids.children.create(name: "グローブ")
baby_kids_5 = baby_kids.children.create(name: "プロテクター")
baby_kids_6 = baby_kids.children.create(name: "ジャケット")
baby_kids_7 = baby_kids.children.create(name: "革ツナギ")
baby_kids_8 = baby_kids.children.create(name: "雨具")
baby_kids_9 = baby_kids.children.create(name: "靴")
baby_kids_10 = baby_kids.children.create(name: "バック")
baby_kids_11 = baby_kids.children.create(name: "パンツ")
baby_kids_12 = baby_kids.children.create(name: "シャツ")
baby_kids_13 = baby_kids.children.create(name: "フェイスマスク/ネックウォーマー")
baby_kids_14 = baby_kids.children.create(name: "その他")

# メンテナンス
interior_residence_accessory = Category.create(name: "メンテナンス")
interior_residence_accessory_1 = interior_residence_accessory.children.create(name: "メンテナンスすべて")
interior_residence_accessory_2 = interior_residence_accessory.children.create(name: "バッテリー")
interior_residence_accessory_3 = interior_residence_accessory.children.create(name: "オイル")
interior_residence_accessory_4 = interior_residence_accessory.children.create(name: "フィルター")
interior_residence_accessory_5 = interior_residence_accessory.children.create(name: "スタンド")
interior_residence_accessory_6 = interior_residence_accessory.children.create(name: "工具")
interior_residence_accessory_7 = interior_residence_accessory.children.create(name: "その他")

# その他
book_music_game = Category.create(name: "その他")
book_music_game_1 = book_music_game.children.create(name: "すべて")
book_music_game_2 = book_music_game.children.create(name: "ファッション")
book_music_game_3 = book_music_game.children.create(name: "グッズ")
book_music_game_4 = book_music_game.children.create(name: "カタログ")
book_music_game_5 = book_music_game.children.create(name: "マニュアル")
book_music_game_6 = book_music_game.children.create(name: "本/雑誌")
book_music_game_7 = book_music_game.children.create(name: "その他")       

ターミナルで % rails db:seed でこのデータを反映させます。

Sequel pro(ホットケーキがアイコンのもの)をインストールしている方は、それにデータがちゃんと反映されているか確認して見て下さい。
ちゃんと反映されていたら下記の画像のようになります。
ファイル名
ancestry カラムのデータ中の NULL の所が親カテゴリーです
コントローラーの入力の所で必要な知識になるので覚えて置いてください。

ちなみに、上記の記事を参考にして貰えば分かりますが、
lady = Category.create(name: "パーツ") ←この形の記載が親のカテゴリー(第1階層)
baby_kids_1 = baby_kids.children.create(name: "バイクウェアすべて") ←この形の記載が子カテゴリー(第2階層)の記載になります。

もし入力するカラム名などに不備があった場合は以下のコマンドを入力してseed.rbを修正しましょう。
% rails db:migrate:reset
修正してもう一度rails db:seed
% rails db:seed

最後に、categoryモデルで ancestryを使用できるようにモデルに下記を記載します。

category.rb
has_ancestry

以上で、ancestryの導入は終了です!




HTMLで多階層の形を実装

続いては、HTMLで多階層の形を実装していきます。
下記のものが、コードになります。

index.html.haml
.categories
  .categories--contents
    .categories--title カテゴリから探す
    %ul.category__parent
      - @parents.each do |parent|
        .category-box{id: "parent_category#{parent.id}"}
          %p.parent_category{id: "parent#{parent.id}"}
            = "#{parent.name}"
          %i.fas.fa-angle-down
        %ul.category__child{id: "parent_list#{parent.id}"}
          - parent.children.each do |child|
            .category-box{id: "parent_category#{child.id}"}
              = link_to "#{child.name}", "#", class: "parent_category",id: "child#{child.id}"
              %i.fas.fa-angle-right


続いて、コントローラーの記載です。

xxxxx_controller.rb
def index
  @parents = Category.where(ancestry: nil)
end

先ずは、HTMLでも使っているので、コントローラーの変数の説明から

これは、Categoryテーブルの ancestryカラムの nilのデータ、
要は上記のSequel proの画像を見て貰えればと思いますが、NULLと書かれたデータを
取り出して、parentsという変数に代入しています。
つまり、親カテゴリーのデータを取り出しているという事ですね。

続いてHTMLの説明ですが、
- @parents.each do |parent|
コントローラーで作った変数parents と eachメソッドを使って、
親カテゴリー(第1階層)のデータを抽出します。

- parent.children.each do |child|
これも同様に eachメソッドを使って、
子カテゴリー(第2階層)のデータを抽出します(理屈よりもこの形で覚えた方が早いと思います)

いくつかあるid:"xxxxx"の部分は、jQueryのイベントの際に、またCSSでのコーティングの際に必要になるので、わざわざidを振っています。

このままでは、子カテゴリー(第2階層)が見えたままなので、display: noneで消しましょう。

xxxxx.css
.category__child{
  display: none;
}

これで、HTMLで多階層の形を実装は終了です!

最後に、jQueryの実装です。



jQuery(JavaScript)で、第1階層のカテゴリーをクリックすると、第2階層のサブメニューが表示されるイベントを記載する

それでは、最後にイベントを発火させるjQueryの記載をしましょう。
下記のものが、コードになります。

$(function(){
  $('#parent_category1').click(function(){
    $("#parent_list1").slideToggle('1000');
  });
  $('#parent_category13').click( function(){
    $("#parent_list13").slideToggle('1000');
  });
  $('#parent_category27').click(function(){
    $("#parent_list27").slideToggle('1000');
  });
  $('#parent_category42').click(function(){
    $("#parent_list42").slideToggle('1000');
  });
  $('#parent_category50').click(function(){
    $("#parent_list50").slideToggle('1000');
  });
});

ここで注意なのですが、コード自体はそれ程難しいものではないと思うのですが、
parent_category"1" parent_list"1" などの数字の部分に注意が必要です。

上記の seed.rb をそのままコピペした方は特に問題ないと思いますが、
自分で作成したという方は、恐らくここの数字が変わってくると思いますので、
大変恐縮ですが、ご自身で検証画面を見て、この数字の部分を確認してみてください。

コードの説明ですが、とても簡単です。
parent_category1(親カテゴリー)の階層をクリックしたら、parent_list1(子カテゴリー)が
表示されるというシンプルなものになっています。

この実装にはslideToggleメソッドを使用しています。
このメソッドは、指定された要素が表示されている時はslideUpで非表示にし、非表示になっている時はslideDownで表示するというメソッドになります。ちなみに、格好の中の数字〔slideToggle('1000')〕は、スライドのスピードです。

このメソッドについて詳しく知りたい方はこちらの記事を参照ください。
slideToggle()メソッドについて




これで、全ての実装が完了です!
実装出来なかったなどの不備が有ればご連絡ください!

ありがとうございました。

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

よく使うCSSのカラーコードについて

■ はじめに

普段、何気なく使っているCSSのカラーコードについて、記事にしましたのでご覧下さい。
この記事について得られる事は以下の通りです。

・カラーコードの構成・仕組み
・カラーコードの記述(短縮方法)

■ 16進数のカラーコード構成

.test {
  color: #112233;
}

最初の2桁(11):赤
次の2桁(22):青
最後の2桁(33):緑
で構成し、16進数で表現されている

16進数 → 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f

・何故、10進数ではないのか

→ 10進数では色の情報量が不足し色を表現しきれない為。

10進数 → 10*10*10*10*10*10 = 1,000,000
16進数 → 16*16*16*16*16*16 = 16,777,216

■ 色の指定方法について

- 16進数
#112233

→ 最も使用頻度が高い

- 16進数の短縮した書き方
#ffffff → #fff
#112233 → #123
#ff0000 → #f00

→ 赤青緑の2桁が同じであれば短縮できる


- キーワードで指定する
red

→ 要素に色をつけて分かりやすくする等。一時的に使用する

コードを短縮することで、素早くスッキリした形で書けて修正も簡単。
但し、会社やチーム等で指定がある場合は指示に従う。

ただ、16進数とキーワードは混同させず、どちらを使うか事前に決めておいた方が良い。
チーム開発で書いたコードを後から見直すと、ごっちゃになっていました。

他にもRGBやHSLといった、色の他に透過度も指定した方法もありますが、ここでは割愛します。

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

【初心者でもわかる】CSSで半円を作る方法

どうも7noteです。今回は半円の作り方

正円や楕円形はよく使われるので情報が多いのですが、
意外と使われない半円の作り方を紹介。

作り方

div {
  width: 200px;          /* 直径の長さ */
  height: 100px;     /* 半径の長さ */
  border-top: 100px solid #000; /* 半径の長さ */
  border-radius: 100%;   /* 角丸100%を指定 */
}

これだけで、半円を作れます。

half.png

補足

上半分にする時はborder-top。下半分のときはborder-bottom
このときはheightを半径の長さにしてください。

逆に左右に作るときはwidthを半径の長さにして、heightを直径の長さに指定します。
transformも使うと、回転できるので好きな角度の半円を作れますね。

おそまつ!

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

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