なるの備忘録

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

SCSSで超便利な幅調整クラスを作る

「ここだけピンポイントでマージンが欲しい」ときに便利な幅調整クラスを作る

HTML、CSSで画面コーディングをしていると、「ここだけピンポイントでマージンが欲しいんだよな」ってときがあると思います。
FLOCCSなどでクラス設計をしているときには「Utillity」という概念はありますが、SCSSファイルへの記述が面倒なので便利な幅調整クラスを作ります。

論よりコード

// 指定可能なmargin,paddingの範囲を定義
$adjust-min: 0;
$adjust-max: 120;

//幅調整用のstyleを作る関数
@for $i from $adjust-min through $adjust-max {
  .mt#{$i} {
    margin-top: #{$i}px !important;
  }

  .mr#{$i} {
    margin-right: #{$i}px !important;
  }

  .mb#{$i} {
    margin-bottom: #{$i}px !important;
  }

  .ml#{$i} {
    margin-left: #{$i}px !important;
  }

  .pt#{$i} {
    padding-top: #{$i}px !important;
  }

  .pr#{$i} {
    padding-right: #{$i}px !important;
  }

  .pb#{$i} {
    padding-bottom: #{$i}px !important;
  }

  .pl#{$i} {
    padding-left: #{$i}px !important;
  }
}

幅調整したい要素のタグには以下のように記述します。

<div class="mt#16">これでmargin-top: 16px;が適用されます</div>

クラス名で「mt#16」(16は任意の数字)のように記載すると、関数が実行され、任意の数字のマージンを持ったstyleが生成されます。
そのstyleが、記載したクラス「mt#16」に適用されるので、結果として任意のmarginやpaddingが適用されます。

最後に

応用すると4方向のmarginやfont-sizeなどにも利用できますね。
ただし、使いすぎるとクラス設計がひどいことになりますので、用法用量を守りましょう。

LaravelのRequestを使ったバリデーションで自分自身の重複は無視したいとき

プロフィール更新の際に、自分自身のデータすら重複チェックに引っかかる

Laravelのバリデーションで重複チェックを入れていると、プロフィール更新の際に、自分自身のデータすら重複チェックに引っかかります。
なので、自分自身の値は無視して、重複チェックをしたいと思います。
(記事自体はたくさんあるのですが、Requestsを使ったちょうど良い記事が見つからなかったので…)

Requestsの中のPHPファイルに以下のように記載します。

    public function rules()
    {
        return [
            'name' => 'required|string|max:255|unique:users,name,'.Auth::user()->name.',name',
            'email' => 'required|string|email|max:255|unique:users,email,'.Auth::user()->email.',email',
            'profile' => 'string|max:255',
            'pic_icon' => 'string|max:255'
        ];
    }

# unique:ユニークチェックをしたいテーブル名,ユニークチェックをしたいカラム名,ユニークチェックを除外したい値,ユニークチェックを除外したいカラム名

gulp利用時に「ReferenceError: internalBinding is not defined」のエラー

gulpを利用しようとしたらReferenceError: internalBinding is not definedのエラーが出た。

以下の記事を見たら「Try updating natives to the latest version. 」とのこと。
stackoverflow.com

以下のコマンドを実施して解決。
$ npm i natives@latest --no-save

参考
(当然ですがバージョン指定してアップデートでも良さそうですね。)
github.com

ボタンを押したら画面外からスライドして表示されるメニューの作り方と注意点

ボタンを押したら画面外からスライドして表示されるメニューの作り方

ボタンを押すと表示されるメニューを簡単に作っていきます。
動作イメージは以下。

画面に表示されるボタンを押すと…
f:id:narunaru7638:20190504001751p:plain

上からにゅ~っとメニューが現れます。
再びボタンを押すと閉じます。
f:id:narunaru7638:20190504001803p:plain

論よりコード

HTML

<!DOCTYPE html>
<html lang="ja">
    <head>
        <link rel="stylesheet" href="style.css">        
    </head>
    <body>
        <div class="cover js-cover">
            <div class="list">test1</div>
            <div class="list">test2</div>
            <div class="list">test3</div>
            <div class="list">test4</div>
            <div class="list">test5</div>            
        </div>
        <div class="btn js-toggle-cover">ボタン</div>    
    </body>
    <script
            src="https://code.jquery.com/jquery-3.3.1.min.js"
            integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
            crossorigin="anonymous"></script>
    <script src="app.js"></script>
</html>

CSS

.cover{
    width: 100vw;
    height: 100vh;
    background-color: black;
    opacity: 0.5;
    position: fixed;
    top:0;
    z-index: 2;
    /* ボタンを押す前は見えないようにメニューは画面外にずらす */
    transform: translateY(-100%);
    transition: .5s;
}

.list{
    font-size: 100px;
    color: red;
    text-align: center;
}

/*ボタンをクリックするとactiveクラスが付与される*/
.active{
    /* Y方向に要素を移動させる */
    transform: translateY(0%);
    transition: .5s;
}

.btn{
    cursor: pointer;
    font-size: 100px;
    border: 1px solid black;
    background-color: white;
    position: fixed;
    z-index: 3;
    top: 50%;
}

JavaScript

$('.js-toggle-cover').on('click', function () {
    $('.js-cover').toggleClass('active');
});

まとめ

・メニューの画面を作っておき、transform: translate() ;を使い、画面外に表示しておく。
・ボタンがクリックされたら、JSでクラスを付与し、画面に表示されるようにCSSを適用する。

注意点

下記のように、画面サイズの縦方向が小さくなってしまうと画面上部から、メニューの要素がはみ出してきてしまいます。
画面サイズと同じだけメニューの要素はずらして画面外に表示していますが、画面が小さくなると十分な量ずらすことができず、その分メニューの要素がはみ出して表示されてしまいます。
f:id:narunaru7638:20190504001845p:plain

なのでメニューを移動させる方向はヨコ方向(X方向)がオススメです。
特にスマートフォンのソフトキーボード(文字入力しようとしたときに表示されるキーボード)によって、表示画面が小さくなったときに上記の減少が起こりやすいです。
(ソフトキーボード利用時の挙動はブラウザの開発ツールでは確認できないので気が付かないことも多いと思います。)

追伸

Twitterでコメントを頂いたのですが、slideToggleを使うのが良さそう。(特に縦方向のアニメーションで表示させたい場合)
以下、コード(HTMLは特に変更なし)

CSS

.cover{
    width: 100vw;
    height: 100vh;
    background-color: black;
    opacity: 0.5;
    position: fixed;
    top:0;
    z-index: 2;
}

.list{
    font-size: 100px;
    color: red;
    text-align: center;
}

.btn{
    cursor: pointer;
    font-size: 100px;
    border: 1px solid black;
    background-color: white;
    position: fixed;
    z-index: 3;
    top: 50%;
}

JavaScript

$('.js-toggle-cover').on('click', function () {
    $('.js-cover').slideToggle('slow');
});

多少アニメーションの差異はありますが、特に気にするほどでなければ、こちらの実装のほうが良さそうですね。(特に縦方向のアニメーションの場合)

Android端末対応の縦書き明朝はNoto Serif JPを使おう

Android端末では明朝体フォントが使いたい

どうやら最近のAndroid端末では明朝体フォントがインストールされていないようです。
PCでは明朝体が表示されるのにスマホだと表示されない理由は上記になります。
そのため必然的にWebフォントを利用することになります。

明朝体で縦書きをするならばNoto Serif JPを使おう

Webフォントで日本語の明朝に対応しているとなると「さわらび明朝」か「Noto Serif JP」が選択肢になります。
結論から言うと、「さわらび明朝」は縦書きだと崩れるので、「Noto Serif JP」がおすすめです。
実際に見てもらったほうが早いと思うので、以下コードです。

HTML

<!DOCTYPE html>
<html lang="ja">
    <head>
        <link rel="stylesheet" href="style.css">        
        <link href="https://fonts.googleapis.com/css?family=Noto+Serif+JP" rel="stylesheet">
        <link rel="stylesheet" href="https://fonts.googleapis.com/earlyaccess/sawarabimincho.css">
    </head>
    <body>
        <p class="font-test sawarabi-line">これはさわらび明朝の横書きです</p>
        <p class="font-test sawarabi-column">これはさわらび明朝の縦書きです。すこしずれているのが分かりますか?</p>
        <p class="font-test notoserif-line">これはNoto+Serif+JPの横書きです</p>
        <p class="font-test notoserif-column">これはNoto+Serif+JPの縦書きです</p>
        <p class="font-test notoserif-column">これはNoto+Serif+JPの縦書きです</p>
    </body>
</html>

CSS

.font-test{
    float:left;
}
.sawarabi-line{
    font-family: "Sawarabi Mincho", serif;
}

.sawarabi-column{
    writing-mode: vertical-rl;
    font-family: "Sawarabi Mincho", serif;
}

.notoserif-line{
    font-family:'Noto Serif JP', serif;
}

.notoserif-column{
    font-family:'Noto Serif JP', serif;
    writing-mode: vertical-rl;
}

画面表示

f:id:narunaru7638:20190502232210p:plain

まとめ

Android端末対応の縦書き明朝はNoto Serif JPを使おう。

【未解決】flexboxの子要素の位置指定とpositionは同時に利用できなさそう

flexboxで等間隔に並べたリストをpositionで画面上部に固定したいが…

タイトルの通りです。flexboxで等間隔に並べたリストをpositionで画面上部に固定したかったのですが、どうもうまくいかなかったので改めて調べてみました。

サンプルコード

HTML

<!DOCTYPE html>
<html lang="ja">
    <head>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <h1>flexboxとpositionのテスト</h1>
        <div class="listArea">
            <ul class="list">
                <li class="listItem">A</li>
                <li class="listItem">B</li>
                <li class="listItem">C</li>
                <li class="listItem">D</li>
            </ul>
        </div>
    </body>
</html>

CSS(positionなし)

.list{
    display:flex;
    align-items: center;
    justify-content: space-around;
}
.listItem{
    margin: 10px;
    list-style: none;
    border: 1px solid black
}

画面表示(positionなし)

f:id:narunaru7638:20190430105837p:plain

この時点では、 justify-content: space-around;が効いて、要素が親要素の両端まで等間隔に並んでいることが分かります。

CSS(positionあり)

.listArea{
    position: fixed;
}
.list{
    display:flex;
    align-items: center;
    justify-content: space-around;
}
.listItem{
    margin: 10px;
    list-style: none;
    border: 1px solid black
}

画面表示(positionあり)

f:id:narunaru7638:20190430110003p:plain

position: fixed;を記載した途端、justify-content: space-around;が効いていないことが分かります。
position:absolute;などでも同様でした。
またulタグにpositionを適用しても同様の結果になりました。

解決法

とりあえずpositionを使うときは、justify-contentを使わずにmarginなどで感覚調整するのが良さそうだなあ。
(どなたか解決法をご存知でしたら教えて下さい。)

【予約語に注意】FuelPHPでユーザ登録をしようとすると「Fuel\Core\Database_Exception [ 1064 (1064) ]: You have an error in your SQL syntax;」と出る

FuelPHPでユーザ登録をするとエラーが出る。

FuelPHPでユーザ登録をしようとすると以下のようなエラーが出た。

Fuel\Core\Database_Exception [ 1064 (1064) ]:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group, profile_fields, last_login, login_hash, created_at) VALUES ('test8', 'zGE' at line 1 [ INSERT INTO users (username, password, email, group, profile_fields, last_login, login_hash, created_at) VALUES ('test8', 'zGEG+uMfdUKF9EJ4dPFONfP4OKlu33BkVIr6wLUDa4M=', 'test8@mail.com', 1, 'a:0:{}', 0, '', 1556079498) ]

どうやらINSERT文自体が間違っているらしい。

直接DBでSQLを実行してみる

直接DBでSQLを実行してみるとここでもエラー。
一つ一つカラムを外していくと、どうやらgroupというカラムが原因のようだ。

カラム名予約語が使われているときは「`」で囲う

SELECT、DELETE、または BIGINT などの特定の語は、テーブル名やカラム名などの識別子として使用するために予約されており、特別な取り扱いが必要となる。
今回の場合は、カラム名として使用されている「group」が予約語のため(group byで使用)、エラーが起きていたよう。

※参考
dev.mysql.com

そんな時はカラム名を「`(バッククォート)」で囲めば解決。
今回の場合だと以下のように実施。

INSERT INTO users (username, password, email, `group`, profile_fields, last_login, login_hash, created_at) VALUES ('test8', 'zGEG+uMfdUKF9EJ4dPFONfP4OKlu33BkVIr6wLUDa4M=', 'test8@mail.com', 1, 'a:0:{}', 0, '', 1556079498)
gontora.hatenadiary.com

これで直接DBでSQL文を実行してみると、無事データ登録が出来た。

FuelPHPが自動的に生成しているSQL文での予約語対策

しかし今回のSQL文はFuelPHPが自動的に生成しているので、実際のコードを実施したときは依然エラーが出る。

調べてみるとどうやら、config/db.php 等で設定している、使用しているデータベース設定の identifierを以下のように設定する必要があるそう。

'identifier'   => '`',

これでカラム名がバッククォートで括られるように設定されるようだ。

db.phpファイル全体だとこんなイメージ。

<?php
return array(
    'active' => 'mysqli',
    'mysqli' => array(
        'type' => 'mysqli',
        'connection' =>array(
            'hostname'      => 'localhost',
            'database'      => 'framework',
            'username'      => 'root',
            'password'      => 'root',
            'persistent'    => false,
            'compress'      => false,
        ),
        'identifier'   => '`',
        'table_prefix'  => '',
        'charset'       => 'utf8',
        'caching'       => false,
        'profiling'     => true,
    ),
);

これで無事登録できました。
このへんはFuelPHPでもバージョンで違うよう。
最近のバージョンはデフォルトで設定されていないのかな?

※参考
teratail.com