なるの備忘録

エンジニアリングそして営業ができるエンジニアに向けて、日々学んだことをアウトプットしていきます。

「クラス名:nth-of-type(n)」で記載した場合、「クラスでn番目」ではなく、「要素でn番目」という数え方になる

「クラス名:nth-of-type(n)」で記載した場合、「クラスでn番目」ではなく、「要素でn番目」という数え方になる

「クラス名:nth-of-type(n)」で記載したときの挙動が気になったのでメモ。
以下の簡単なコードで動作を確認します。

簡単な動作確認用コード

HTML

<!DOCTYPE html>
<html lang="ja">
    <head>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <div>            
            <span class="a">その要素で1番目⇛aクラス</span>
            <span class="b">その要素で2番目⇛bクラス</span>
            <!-- クラスに適用されていたならこの要素は青色になる(class="a"の中で2番目のため)-->
            <span class="a">その要素で3番目⇛aクラス</span>
            <span class="b">その要素で4番目⇛bクラス</span>
            <!-- クラスに適用されていたならこの要素は青色になる(class="a"の中で3番目のため)-->
            <span class="a">その要素で5番目⇛aクラス</span>
            <span class="b">その要素で6番目⇛bクラス</span>
        </div>
    </body>
</html>

CSS

.a:nth-of-type(1){
    background-color: red;
}
.a:nth-of-type(2){
    background-color: blue;
}
.a:nth-of-type(3){
    background-color: yellow;
}
.a:nth-of-type(4){
    background-color: green;
}

※nth-of-type(n)は、疑似クラスの一種で、 n番目のその種類の要素にスタイルを適用

実施結果

f:id:narunaru7638:20190422004455p:plain

まとめ

・「クラス名:nth-of-type(n)」で記載した場合、「クラスでn番目」ではなく、「要素でn番目」という数え方になる
・要素でn番目かつそのクラス名をもつものにスタイルが適用される
・「クラス名:nth-of-type(n)」で記載したときは、勘違いしやすいので注意(特に兄弟要素に同じ種類の要素があると間違えやすい)

コマンドラインでfuelPHPがインストールできないときの対策(syntax error near unexpected token `newline')

コマンドラインfuelPHPがインストールできないときの対策(syntax error near unexpected token `newline')

コマンドラインfuelPHPをインストールしようとしたら、以下のようなエラーがでました。

$ curl get.fuelphp.com/oil | sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   239  100   239    0     0    118      0  0:00:02  0:00:02 --:--:--   118
sh: line 1: syntax error near unexpected token `newline'
sh: line 1: `<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">'

解決策

以下のコマンドを実施して、このようにPCのPasswordを求められればOKです。

$ curl https://get.fuelphp.com/oil | sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   479  100   479    0     0    437      0  0:00:01  0:00:01 --:--:--   437
Password:

このコマンドの差分からして、どうやらhttpsで取得をしないといけないようですね。

Sassの変数と@mixinでレスポンシブデザインを作るときは@mixinの呼び出し順に注意

Sassの変数と@mixinで3パターンのレスポンシブデザインを作ろうとすると、CSSが適用されない

PC・タブレットスマホの3パターンのレスポンシブデザインをSassの変数と@mixinで作ろうとして、CSSがうまく適用されませんでした。
結論としては、Sassの変数と@mixinでレスポンシブデザインを作るときは、ブレイクポイントの変数の用意の仕方で、@mixinの呼び出し順が異なります。
これによって一見CSSが適用されていないように見えてしまいます。

そもそも「Sassの変数と@mixinを使ってレスポンシブデザイン」を作る方法は?

こちらに素晴らしく分かりやすいサイトがございますので、こちらを御覧ください。
www.tam-tam.co.jp

本題:@mixinの呼び出し順について

用意したブレイクポイントの変数

$breakpoints: (
  'sm': 'screen and (max-width: 414px)',
  'md': 'screen and (max-width: 768px)',
  'lg': 'screen and (max-width: 1000px)',
  'xl': 'screen and (max-width: 1200px)',
) !default;

用意したmixin

@mixin mq($breakpoint: md) {
  @media #{map-get($breakpoints, $breakpoint)} {
    @content;
  }
}

@mixinでメディアクエリを呼び出す

正しい呼び出し順

.container {
  width: $site-width;

  @include mq(md) {//画面サイズが768pxまでの場合、styleを適用
    width: 90%;
  }

  @include mq() {//画面サイズが414pxまでの場合、styleを適用
    width: 80%;
  }

誤った呼び出し順

.container {
  width: $site-width;

  @include mq() {//画面サイズが414pxまでの場合、styleを適用
    width: 80%;
  }

  //mq() で呼び出して適用したstyleが上書きされてしまう
  @include mq(md) {//画面サイズが768pxまでの場合、styleを適用
    width: 90%;
  }

まとめ

今回は用意したブレイクポイントの変数は「 'sm': 'screen and (max-width: 414px)',」のように「 max-width」で条件を定義しています。
この場合は、あとからstyleが上書きされないように、PC⇛タブレットスマホの順に@mixinを呼び出します。
そのためブレイクポイントの変数を「min-width」で定義した場合は、@mixinの呼び出し順は今回と逆になります。

yarnでnode-sassのライブラリを使うと「An output directory must be specified when compiling a directory」とエラーが出る

単なる打ち間違いですが、わりとハマってしまったのでメモ。

jsonファイルの中身

{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build-css": "node-sass --include-path scss scss/style.scss css/style.css",
    "watch-css": "nodemon -e scss -x \"npm run build-css\""
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "node-sass": "^4.11.0",
    "nodemon": "^1.18.11"
  }
}

node-sassのライブラリをbuild-cssというコマンドを作成して実施しようとしています。

ターミナルでの実行およびエラー画面

$ yarn build-css
yarn run v1.15.2
$ node-sass --include-path scss scss/style.scss css/style.css
An output directory must be specified when compiling a directory
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

yarnでbuild-cssを実行。
「An output directory must be specified when compiling a directory」、すなわち「ディレクトリをコンパイルするときは、出力ディレクトリを指定する必要があります。」と怒られていますね。

結論

・出力するディレクトリではなく、読み取る側のディレクトリ名が間違っていました。
「誤:sccsディレクトリ内にstyle.scssを格納」⇛「正:scssディレクトリ内にstyle.scssを格納」

エラーメッセージに引っ張られすぎた…

CSSのアニメーション機能を使って、扉から飛び出すように画像を表示させる

せっかく学習したのでCSS3のアニメーション機能を使って、扉から飛び出すような画像表示機能を作ってみます。

動作イメージ

最初は扉のような画像が表示されています。
f:id:narunaru7638:20190416230842p:plain

扉にカーソルを重ねると勢いよく扉が開きます。
f:id:narunaru7638:20190416230859p:plain

直後に勢いよく画像が飛び出してきます。
f:id:narunaru7638:20190416230905p:plain

カーソルを画像から離すと画像は小さくなり、扉は閉まります。
f:id:narunaru7638:20190416230930p:plain

論よりコード

HTML

<!DOCTYPE html>
<html lang="ja">
    <head>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <div id="main">
            <!--  疑似要素:after,:beforeを付けるためにimgタグをspanタグで囲う   -->
            <!--  imgタグのような閉じタグが無い要素は疑似要素が使えない  -->
            <span class="wrap-img"><img src="img/image.png" alt=""></span>
        </div>
    </body>    
</html>

CSS

#main{
    padding: 200px;
}
.wrap-img{
    display: block;
    width: 800px;
    height: 800px;
    position: relative;
    z-index: 0;
    visibility: middle;
    box-sizing: border-box;
    transition: all .3s;
}
/*疑似要素:before,:after*/
/*html上には無いが、要素の前後に要素があるようにできる*/
/*htmlを汚さずにデザインのための要素を付けることが可能*/
.wrap-img::before,
.wrap-img::after{   
    position: absolute;
    /* 画像より手前に表示するため   */
    z-index: 1;
    display: block;
    content: '';
    box-sizing: border-box;
    top: 0;
    /* 親要素の半分の大きさの扉のため*/
    width: 50%;
    height: 100%;
    background-color: rgba(208, 162, 67, 1);
    border: rgba(128, 0, 0, 1) 2px solid;
    box-sizing: border-box;
    /* 0.1秒待った後に0.3秒かけてwidthが変化する(扉が閉まる)   */
    transition: width .3s ease .1s;
}
/*左側の扉となる要素*/
.wrap-img::before{
    left: 0;
}
/*右側の扉となる要素*/
.wrap-img::after{
    right: 0;
}
.wrap-img:hover::before,
.wrap-img:hover::after{
    cursor: pointer;
    /*カーソルを重ねるとwidthを0にする(扉が開く)*/
    width: 0;
    /* 0秒待った後に0.3秒かけてwidthが変化する   */
    transition: width .3s ease 0s;
}
img{
    box-sizing: border-box;
    display: block;
}
img{
    /* カーソルを重ねていないときの画像は小さく   */
    transform: scale(0.8, 0.8);
    transform: all .1s;
}
img:hover{
    cursor: pointer;
    /*  カーソルを重ねると画像は大きくなる   */
    transform: scale(1.2, 1.2);
    transition: transform .2s ease .1s;
}

ポイントまとめ

・疑似要素:before,:afterを使うことで、htmlを汚さずにデザインのための要素を付けることが可能
・imgタグのような閉じタグが無い要素は疑似要素が使えない
・疑似要素のwidthを50%にし、positionを調整、z-indexで画像の手前に持ってくることで扉のように見せる
・扉にカーソルを重ねたらtransitionでwidthを0に変化させる(待ち時間や変化の早さを指定可能)
・扉が空いたら画像が飛び出てくるようにtransitionで画像の大きさが変化する早さを調整

基本的なクロージャの実践例の「モジュールパターン」は何が起きているの?

なんとなくクロージャーは分かったけど…

JavaScriptのスコープの概念」や「クロージャーのメリット」は理解したけど、いまいち典型的なクロージャーのコードで何が起きているか分からなかったので調べてみました。

典型的なクロージャーのコードと分からんポイント

var module = (function() {//分からないポイント①: functionの前に"("がついて、function全体が()で囲われている
    var count = 0;

    return {
        increment: function() {//分からないポイント②:セミコロンの隣のfunctionという見慣れない記述
            count++;
        },
        show: function() {
            console.log(count);
        }
    };

})();//分からないポイント③:最後の謎の何も入っていない()

//分からないポイント④:〇〇.関数名();でよく分からんけど関数を呼べる?
module.show(); // 0

module.increment();
module.show(); // 1

console.log(count); // undefined

だいたいこのあたりがよく分からないポイントだと思います。

要点1:クロージャーは即時関数を使って記載されている

典型的なクロージャーのコードは即時関数というものを使って記載されています。
即時関数は、関数を定義すると同時に実行するための構文。

基本的な書き方

(function () {
    //処理
}());

引数と返り値

var result = (function (param1, param2) {
    return param1 + param2;
}(1, 2));

console.log(result); //3

つまり「変数module」に、関数を定義したと同時にその「関数を実行した結果」が入っていることが分かります。ここでいう「関数を実行した結果」とは「returnの中身」ですね。
「console.log(module);」を実施すると「increment」と「show」という関数が入っているのが分かると思います。

var module = (function() {//分からないポイント①: functionの前に"("がついて、function全体が()で囲われている
    var count = 0;

    return {//分からんポイント②:returnに関数が入ってる
        increment: function() {//分からないポイント②:セミコロンの隣のfunctionという見慣れない記述
            count++;
        },
        show: function() {
            console.log(count);
        }
    };

})();//分からないポイント③:最後の謎の何も入っていない()

//分からないポイント④:〇〇.関数名();でよく分からんけど関数を呼べる?
module.show(); // 0

module.increment();
module.show(); // 1

console.log(module);//incrementとshowという関数が入っているのが分かる

console.log(count); // undefined

開発ツールで見てみるとincrementとshowという関数が確かに入っていますね。
f:id:narunaru7638:20190416000953p:plain

これで「分からないポイント①」と「分からないポイント③」は理解できたと思います。

要点2:JavaScriptで扱うものはすべてオブジェクトかオブジェクトのように使える

JavaScriptで扱うものはすべてオブジェクトかオブジェクトのように使えます。
オブジェクトにはプロパティとメソッドがあります。

オブジェクトの作り方と利用例

//testHumanというオブジェクトを作成
var testHuman = {
    firstName: "Hoge",
    lastName: "Fuga",
    sayHello: function(){ console.log("Hello") }// メソッドを作成
};

console.log(testHuman["firstName"]);  // Hoge
console.log(testHuman["lastName"]);  // Fuga
testHuman.sayHello();// Hello メソッドを実施

上記のtestHumanオブジェクトのsayHelloメソッド作成と同様の方法で、moduleオブジェクトのincrementメソッドとshowメソッドを作成していることが分かります。testHuman.sayHello();と同様の方法で、「module.increment();」「module.show(); 」を実施していることが分かります。
これで「分からないポイント②」と「分からないポイント④」は理解できたと思います。

自動的に画像がスライドしていく画像スライダーを作る

HTML、CSSJavaScript(jQuery)で自動的に画像がスライドしていく画像スライダーを作ります。
よくWebページのトップバナーがこんな感じに変化していますね。

動作イメージ

ページを開くと1枚目の画像が表示されています。
f:id:narunaru7638:20190413230924p:plain
しばらくすると画像が左にスライドします。(1枚目の画像が少しだけ左に見えるのが分かりますか?)
f:id:narunaru7638:20190413230945p:plain
またしばらくすると画像がさらに左にスライドします。
f:id:narunaru7638:20190413230952p:plain
最後の画像が表示されたあとは、再び1枚目の画像に戻ります。(ここはアニメーションなしで一瞬で戻ります。)
f:id:narunaru7638:20190413231030p:plain
f:id:narunaru7638:20190413230924p:plain

論よりコード

HTML

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ImgSlider</title>
    <link rel="stylesheet" href="style.css">
    <script src="https://code.jquery.com/jquery-3.4.0.min.js" integrity="sha256-BJeo0qm959uMBGb65z40ejJYGSgR7REI4+CW1fNKwOg=" crossorigin="anonymous"></script>
</head>

<body>
   <div class="main">
        <!--スライドを表示させる画面-->
       <div class="slider">
            <!--  横に並べた複数のスライドを格納する用コンテナ  -->
           <ul class="slider__container">
                <!--  各スライド -->
               <img src="img/spring.jpg" alt="" class="slider__item slider__item1">
               <img src="img/summer.jpg" alt="" class="slider__item slider__item1">
               <img src="img/autumn.jpg" alt="" class="slider__item slider__item1">
               <img src="img/winter.jpg" alt="" class="slider__item slider__item1">
           </ul>
       </div>
   </div>

 <script src="app.js"></script>

</body>
</html>

CSS

body{
    background: #f6f5f4;
    color: #333;
}
.main{
    width: 1600px;
    margin: 30px auto;
}

.slider{
    /* スライドを表示させる画面の横幅(≒スライド1枚あたりの横幅) */
    width: 1600px;
    /* スライドを表示させる画面の縦幅(≒スライド1枚あたりの縦幅) */
    height: 1066px;
    /* はみ出した要素は隠れるようにする */
    overflow: hidden;
}
.slider__container{
    /* スライドを表示する画面とスライド1枚をぴったり合わせるため設定 */
    padding: 0;
    margin: 0;
    
    /* 子要素でfloatを利用しているため設定 */
    overflow: hidden;

    list-style: none;

    /* 後ほどJSでleftプロパティを設定するため必要 */
    position: relative;

}
.slider__item{
    /* スライド1枚あたりの横幅 */
    width: 1600px;
    /* スライド1枚あたりの縦幅 */
    height: 1066px;
    /* スライドを横一列に並べる */
    float: left;
}

JavaScript(jQuery)

//最初にどのスライドから表示するかを選択
var currentItemNum = 1;

var $slideContainer = $('.slider__container');

//クラスslider__itemの要素の個数を算出
var slideItemNum = $('.slider__item').length;

//スタイド1つあたりの横幅を算出
var slideItemWidth = $('.slider__item').innerWidth();

//スライド1つあたりの横幅とスライドの個数から
var slideContainerWidth = slideItemWidth * slideItemNum;

//スライドさせる速さ(animateメソッド用)
var DURATION = 1000;

//横に並べた複数のスライドを格納する用コンテナの横幅を設定
$slideContainer.attr('style', 'width:' + slideContainerWidth + 'px');

//スライドを自動的に変化させる関数
function autoSlide(){
    //現在のスライドの番号が全部のスライドの数より少ないとき
    if(currentItemNum < slideItemNum){
        //スライド用コンテナをanimateメソッドで変化させる
        $slideContainer.animate({left: '-='+slideItemWidth+'px'}, DURATION);//現在のCSSのleftのプロパティの値からスライド1つあたりの横幅分変化させる
        currentItemNum++;//現在のスライド番号を1増やす
    //現在のスライドの番号が全部のスライドの数と同じとき
    }else if(currentItemNum = slideItemNum){
        //現在のCSSのleftのプロパティの値を変更(徐々に変化させないのでanimateメソッドは使わない)
        $slideContainer.css('left', '+='+slideItemWidth*(slideItemNum-1)+'px');
        currentItemNum = 1;//現在のスライド番号を1に戻す
    }
}

//setInterval関数で適当な秒数ごとに実施
setInterval(autoSlide, 5000);

ポイントまとめ

・スライドを表示させる画面、複数のスライドを横に並べる用のコンテナ、各スライドの要素を用意
・スライドを表示させる画面に、スライド1枚分が表示されるように、大きさや「overflow:hidden;」を設定
・JSでスライドの横幅や数を取得し、それに合わせてコンテナの大きさや一回のスライドする幅を設定する
・animeteメソッドでコンテナのpositionを変化させる
・setIntervalで定期的に画像をスライド