20200204のCSSに関する記事は6件です。

【CSS】要素の中央寄せ【備忘録】

中央寄せしなければならない時に、毎回調べてるので備忘録

ブロック要素

sample.css
/* 色、幅、高さの記述は省略 */
.contentA{
  /* 親要素 */
  display: flex;
  align-items: center;
}

.contentB{
  /* 子要素 */
  margin: 0 auto;
}
sample.html
<body>
  <div class="contentA">
    <div class="contentB"></div>
  </div>
</body>

実行結果(赤が親要素、青が子要素)

スクリーンショット 2020-02-04 22.22.28.png

インライン要素

インライン要素をdivで囲ってあげる

sample.css
/* 色、幅、高さの記述は省略 */
.contentA{
  /* 親要素 */
  display: flex;
  align-items: center;
}

.contentB{
  /* 子要素 */
  margin: 0 auto;
}

/* ボタンの位置設定は特になし */

sample.html
<body>
  <div class="contentA">
    <div class="contentB">
      <input type="button" value="テストボタン">
    </div>
  </div>
</body>

実行結果(赤が親要素、青が子要素(ボタン))

スクリーンショット 2020-02-04 23.11.37.png

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

CSSでグリッチっぽい表現をやる

jdIOWpguRq.gif

PIXIV TECH FES. ← このサイトかなりカッコいいですよね(私は行けませんが…)(担当したのは@yui540です1

CSSで文字を分割します、面倒くさいので構成はParcelで行きます、JavaScriptは使いませんが現実的なところを考えると要ります(アニメーションの発火を制御するのにとか…)

yarn add parcel-bundler -D
npx parcel src/index.html

この記事は自分でも空でかける自信が無いので備忘録として書き残しておきます(アニメーションまでは面倒くさくなって書かないことになりました、書くのは文字分割までです)

HTML

まずHTMLから

1

<body>
  <div class="wrapper">
    <div class="text-wrapper"><p>そのツイート、切らせてもらう</p></div>
  </div>
</body>

image.png2

まずグリッチしたい要素(今回はp)を.text-wrapperで囲む
.text-wrapperを更に大きな.wrapperで囲む

2

<body>
  <div class="wrapper">
    <div class="text-wrapper"><p>そのツイート、切らせてもらう</p></div>
    <div class="text-wrapper"><p>そのツイート、切らせてもらう</p></div>
    <div class="text-wrapper"><p>そのツイート、切らせてもらう</p></div>
    <div class="text-wrapper"><p>そのツイート、切らせてもらう</p></div>
    <div class="text-wrapper"><p>そのツイート、切らせてもらう</p></div>
    <div class="text-wrapper"><p>そのツイート、切らせてもらう</p></div>
    <div class="text-wrapper"><p>そのツイート、切らせてもらう</p></div>
    <div class="text-wrapper"><p>そのツイート、切らせてもらう</p></div>
    <div class="text-wrapper"><p>そのツイート、切らせてもらう</p></div>
    <div class="text-wrapper"><p>そのツイート、切らせてもらう</p></div>
    <div class="text-wrapper placeholder"><p>そのツイート、切らせてもらう</p></div>
  </div>
</body>

image.png

.text-wrappern + 1個に増やす(nは分割する数です)、今回は10分割するので11個に増やします

最後の要素に.placeholderクラスを付与しておく(次からのCSSでの見通しが良くなるからです(使わない場合は:nth-of-last-typeなどでどうにか気合でやる))

SCSS

forループとかを使うと一般化ができるのでかなり嬉しいのでSCSSで書く、リセットCSSなどでmargin等が消えている前提でCSSを書いていきます

1

.wrapper {
  position: absolute;
  top: 25px;
  left: 25px;
}

概略図
mspaint_mK3RjqrKDt.png

2

.wrapper {
  position: absolute;
  top: 25px;
  left: 25px;
}

.text-wrapper {
  font-size: 3rem;
}

.text-wrapper.placeholder {
  visibility: hidden;
}

.text-wrapper:not(.placeholder) {
  position: absolute;
  top: 0;
  left: 0;
}

image.png

すべての.text-wrapper要素に必要なスタイルを当てる(文字をデカくする)

.placeholder要素は場所を取るだけの要素なので見えないようにしておきます

.placeholder以外の要素はすべて重ね合わせてある状態になっています

概略図

image.png

3

.wrapper {
  position: absolute;
}

.text-wrapper {
  font-size: 3rem;
}

.text-wrapper.placeholder {
  visibility: hidden;
}

.text-wrapper:not(.placeholder) {
  position: absolute;
  top: 0;
  left: 0;
  width: 10%;
  height: 100%;
  overflow: hidden;
  & > p {
    position: absolute;
    top: 0;
    white-space: nowrap;
  }
  @for $i from 1 through 10 {
    &:nth-of-type(#{$i}) {
      left: ($i - 1) * 10%;
      & > p {
        left: -(($i - 1) * 100%);
      }
    }
  }
}

A4imFr318C.gif

気合で理解してほしいです

文字のような要素ではwhite-space: nowrapを指定しないと改行されて壊れます

概略図
image.png

4

.text-wrapper:not(.placeholder) {
  position: absolute;
  top: 0;
  left: 0;
  width: 10%;
  height: 100%;
  overflow: hidden;
  & > p {
    position: absolute;
    top: 0;
    white-space: nowrap;
  }
  @for $i from 1 through 10 {
    &:nth-of-type(#{$i}) {
      top: ($i * 25%); // ← ここで文字を斬る
      left: ($i - 1) * 10%;
      & > p {
        left: -(($i - 1) * 100%);
      }
    }
  }
}

image.png

おー斬れました よかったですね

後はmathsassなどを使って乱数っぽく座標をずらしたりすると良いと思います(29% * sin(1.7922rad * cos(1.9877777777deg * $i) + $i * .7rad)など)、transform, translateなどを駆使して頑張って下さい

一般化

.text-wrapper:not(.placeholder) {
  $n: 30;

  position: absolute;
  top: 0;
  left: 0;
  width: (100% / $n);
  height: 100%;
  overflow: hidden;
  & > p {
    position: absolute;
    top: 0;
    white-space: nowrap;
  }
  @for $i from 1 through $n {
    &:nth-of-type(#{$i}) {
      left: ($i - 1) * (100% / $n);
      & > p {
        left: -(($i - 1) * 100%);
      }
    }
  }
}

作例

画像でも応用できる
odFwwtFj7J.gif

transform: skew()などをやるとかなり意味がわからない動きになってメチャクチャ面白い
iM40d4seu6.gif

以上です

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

Google OAuth 2.0 認証を使ったGoogle Sign-Inの実装(JS編)

概要

最近はどのサイトでもSNSからのログインだったり、登録するサイトが当たり前になっています。

スクリーンショット 2020-02-04 19.43.39.png

よく見かけるこんな感じのボタンですね。。

今回はjsだけを使って簡単にGoogle Sign-Inを実装してみます。

Googleアカウントの作成

まずはじめにGoogleアカウントを作成しましょう。
可能ならそのアプリ専用に作った方がいいと思います。

Google Cloud Platformでの設定

https://console.cloud.google.com/getting-started

まずは先ほど作ったGoogleアカウントでログインしましょう。

左上の[Project]からプロジェクトを作成を選択します。

スクリーンショット 2020-02-04 19.56.46.png

プロジェクト名はわかりやすい任意の名前をつけて、場所はとりあえずこのままで作成します。

先ほど作成したプロジェクトを選択して左のメニューから
[APIとサービス]→[認証情報]を選択

[認証情報を作成]→[OAuth クライアント ID]から今回使うOAuth認証情報を作成します。

スクリーンショット 2020-02-04 20.15.02.png

今回は[ウェブアプリケーション]を選択して[名前]を入力します。

[承認済みのJavaScript生成元]には作ったアプリのDomainを入力します。(複数選択可能)
例:http://localhost:8080

[承認済みのリダイレクトURI]にはユーザーが認証された後にリダイレクトされるURLを設定します。
例:http://localhost:8080/login/callback

[作成]するとクライアントIDが発行されるのでメモしといてください。

実装

では実装してみましょう。

HTML
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="google-signin-client_id"content="YOUR_CLIENT_ID.apps.googleusercontent.com">
    <script src="https://apis.google.com/js/platform.js" async defer></script>
  </head>
  <body>
    <div class="g-signin2" data-onsuccess="onSignIn" data-theme="dark"></div>
  </body>
</html>

正直HTMLにこの記述するだけでGoogle Sign-Inの実装はできちゃいます。
[YOUR_CLIENT_ID]は先ほどメモしたクライアントIDを入力しましょう。
簡単ですよね。

更にログインしたユーザーのプロフィール情報を取得するにはgetBasicProfile()メソッドを使用します。

JavaScript
function onSignIn(googleUser) {
  var profile = googleUser.getBasicProfile();
  console.log('ID: ' + profile.getId()); // GoogleのID
  console.log('Name: ' + profile.getName()); // アカウント名
  console.log('Image URL: ' + profile.getImageUrl()); // プロフィール画像
  console.log('Email: ' + profile.getEmail()); // ユーザーのメールアドレス
}

ちなみにログアウトを追加したい場合は、こんな感じで書けます。

HTML
<a href="#" onclick="signOut();">ログアウト</a>
<script>
  function signOut() {
    var auth2 = gapi.auth2.getAuthInstance();
    auth2.signOut().then(function () {
      // ログアウトした後の処理
    });
  }
</script>

まとめ

今回はJSを使ってGoogle OAuth 2.0 認証を使ったGoogle Sign-Inの実装をしました。
ほんとこれだけでログイン機能の実装はできてしまうので皆さんも今時のおしゃれサイトにする際は使ってみてください。
ただ、実際の運用に使う際はこれだけだとセキュリティーガバガバなのでサーバーサイドでIDトークン検証したりなど、工夫が必要ですね。
また別でサーバーサイドでの処理などの実装もあげるのでよかったらみてください。

参考

https://developers.google.com/identity/sign-in/web

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

初心者によるプログラミング学習ログ 229日目

100日チャレンジの229日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

229日目は

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

:hoverを使ったら無茶チラついたので気になって悩んでしまった

とっても細かいどうでもいいところをなんとか直したくなり無茶時間かけて
試行錯誤した。解決?はしたっぽいがどういう原理なのかよく分からない・・・・

やっぱりフロントは嫌いだ。

やりたかったこと。

隣接した要素で、一方にマウスオーバーすると、
display: none;
にしておいたもう一方の要素を出現させて、
出現させた要素のリンクをクリックできるようにしたい。

CSSで実装する、マウスオーバーで表示される吹き出し

どこのサイトも簡単そうに書いてあり、TECHのカリキュラムでもおかしなことは起こらなかったのだが・・・

chromeで開くとなんかムッチャチラつく。何これ?

画面収録-2020-02-03-21.52.50.gif

色々調べたけど同じことになってる記事を見つけられなかったので、
このhoverの部分だけをhtml,cssに切り出した上でプロパティをどんどん削っていってテストした。

最終的にここまでにしたけど、やっぱり改善せず。ちなみに他のブラウザの動きとして、safariはちょっとチラつく。firefoxはチラつき無し。うん、わかんね。

test.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <link rel='stylesheet' href='./test.css'>
</head>
<body>
  <div class="nickname">名前</div>
  <div class="box"><a href="#">ログアウト</a></div>
</body>
</html>

※ scssは、vseditorにLive Sass Compilerっていうのを入れて、css変換して検証してた。

test.scss
.nickname {
  height: 60px;
  background-color: #f0f0f0;
  &:hover + .box {
    display: block;
  }
}

.box {
  background-color: skyblue;
  display: none;
  position: absolute;
  top: 2em;
  height: 50px;
}

最終的に思い至ったのが(元々、そういう風に書いておくものなのかもしれないが・・・)

nickname要素にのみhoverを適用させた状態だと、nickname要素の範囲からマウスが外れてしまった時にbox要素が消えちゃうじゃん、と思いbox:hover{ display: block; }
を追加したらなんとかなった。

test.scss
.box {
  background-color: skyblue;
  display: none;
  position: absolute;
  top: 69px;
  height: 50px;
  &:hover {
    display: block;
  }
}

ちなみに、topを変えて試してみてたが、
双方の境界部分は、接するか、重ねるかしないとダメ、と思っていたが、
1 pixcel離れるのは許容される(1 pixcelの隙間にマウスオーバーしてもboxが消えずに済む)ということが分かった!!

どうでもいいけど。

ブラウザ別に動作が変わるだろうから、きっと接するか、重ねるかしとくのが無難なんだろう。

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

AtomicDesignでAtomsの設計を失敗した話

概要

今回は、AtomicDesignでのコンポーネント設計をした行った時にやらかしたミスを記事にしてみました。

AtomicDesignって

最初にAtomicDesignとはなんなのかを軽く振り返ってみましょう。
Qiita内外でも多くの説明がなされているので、ざっくりと。

AtomicDesignとは、コンポーネントを以下の5つの階層に分け、
コンポーネントの役割や責任を明確しそれらをルールを決めて分割していこう、という概念です。

  • Atoms(原子)
  • Molecules(分子)
  • Organisms(有機体)
  • Templates
  • Pages

上が最小のコンポーネントで、下が一番大きいコンポーネントとなります。
また、AtomicDesignのルールとして、

  • Atoms
    • これ以上機能として分割できない機能達
  • Molecules
    • Atomsの集合体
  • Organisms
    • AtomsやMoleculesの集合体で、複雑な構成
  • Templates
    • MoleculesやOrganismsを配置する設計図
  • Pages
    • Templatesに対してデータを反映した物

といった感じですね。
それぞれの役割が明確化されていて、コンポーネントをどう作っていけばいいかの方針がわかりやすくなってますね。
それでもやらかした自分とは一体

Atomsをつくってみた

まずは、設計がマズい形のAtomsを見てみましょう
今回はButton要素のコンポーネントを例に使います。

button
<template>
  <button @click="onClick">
    <slot></slot>
  </button>
</template>

<script>
export default {
  methods: {
    onClick() {
      return this.$emit("click");
    }
  }
};
</script>

<style lang="scss" scoped>
.Base__Button {
  &--green {
    //省略
  }
  &--red {
    //省略
  }
  &--yellow {
    //省略
  }
}
</style>

HTML要素とScript要素は至ってシンプルな構成です。
CSS要素に関しては、1つのファイルの中に複数のClass属性が記述する形で作ってみました。
このComponentではclass属性の指定をせずに、Componentを配置した親側でClass属性を指定するという方法をとりました。
呼び出す側の例も書いておきます。

Parent
<base-button class="Base__Button--green">HOGE</base-button>

親でClass属性を指定してる時点でとっても嫌な予感がするぞ

が、だめ!

最初はこの設計でも問題なく使えてましたが、使用するClass属性が増えて、記述が多くなってくると、
当然ながら使いづらくなってきました。

というのも、新しいスタイルが必要となった場合も同じファイルに追加していくために、
アイコンに使用する目的の無色透明で小さめのスタイルを…。
次はタブ用のスタイルを…
次はgreenだけ、ボタンのサイズを色々作りたい
次は…

となり、気づいたらClass属性の記述だけでファットになって、しかも複雑に絡み合い濃厚な味に…。

▂▅▇█▓▒░(‘ω’)░▒▓█▇▅▂ うわあああああああああ

Badな設計

どのような点がBadであったかを確認してみましょう。

  • 親と密結合
    • 親でクラス名を指定しないと見た目を固定できない
    • 下手したら親にスタイルのコードを書いている
  • ComponentのCSSがファット
    • 1つのComponentに色んなスタイルを詰め込みすぎ
  • CSSが上書きなどでスパゲッティコード化
  • Atomsの外でClass属性/CSS属性を記述
    • コンポーネントの状態を閉じ込めれてない

基礎的な注意点ばかりではありますね…。
なぜ、このような設計のComponentを作ってしまったかも反省しておきましょう。

  • 同じようなComponentを作るのはNG
    • 1つのComponentで管理やったら楽じゃん!
  • Atomsのルール通り処理の機能は分割しつつスタイルはまとめたい
  • 色んな箇所で使うなら同じComponentのほうがいいのでは
  • でも色んなデザインにしたいけど細かく制御できないから親にCSS属性を書くしか無い

というのを考えて作りやらかしてしまいました。
特に最後のは、もはやAtomsを親からスタイルを上書きしていたので、
これ普通のButtonタグでもよくない?のとこれ疎結合になっていないよね?という、色々なルール違反な状態となっていました。

そうだ、いっぱいつくればいいんだ

では、どうすればいいんだ!と悩み、色々ググって情報を漁っていたところ気づきました。
色んな人のLT資料や、記事を見ていっそのこと振り切って考えていいのかもと思ってすえたどり着いた答えが、
そうだ、必要な分のAtomsをいっぱいつくればいいんだ

HTML要素やJavascriptと同じように、CSSも見た目毎に最小単位まで絞り込んだComponentを作ってしまえばいいのだと。
方針としては、「Importしたら見た目も完成していたそのまま使える」ぐらいの疎結合と独立感で。
早速、先程のButtonを作り直してみました。
ImportしてるComponentが多くてパス修正が大変だった

BaseButtonGreen.vue
BaseButtonRed.vue
BaseButtonYellow.vue
BaseButtonRadius.vue
BaseButtonSemiRadius.vue

分解し、それぞれ作ってみました。
中身の方は、試しにBaseButtonGreen.vueを見てみましょう。

BaseButtonGreen.vue
<template>
  <button @click="onClick" class="Base__Button--green">
    <slot></slot>
  </button>
</template>

<script>
export default {
  methods: {
    onClick() {
      return this.$emit("click");
    }
  }
};
</script>

<style lang="scss" scoped>
.Base__Button--green {
  //省略
}
</style>

以前のComponentと違うのは、class属性をここで指定しCSSでは他のclass属性を記述していない、というところです。
BaseButtonGreen.vueは名前で表すように緑色のボタンに関係するCSS属性だけを記述し、
BaseButtonRed.vueは、赤色のボタンを。
BaseButtonRadius.vueでは、円形に関係するCSS属性だけを。
こうすることで、親とは疎結合になり独立性が高いComponentとなり、Importしそのまま使える事ができます。

差分がある場合には?

BaseButtonGreen.vueの縦横幅を大きい/小さいのを使いたいとなった場合ですが、
この場合はBaseButtonGreen.vueの中に差分を書くのではなく、いっそのこと別Componentにしましょう。

BaseButtonGreen.vue
BaseButtonGreenLarge.vue
BaseButtonGreenSmall.vue

ファイル名に修飾子で「Large」か「Small」などを付け加えて、違いを明確化。
このように、同じ構成や見た目だけど細部が微妙に違うAtomsを作る場合には、ファイル名に修飾子をつけました。
サイズだけではなく、hoverなどの擬似クラスでちょっとリッチなエフェクトを付けたいけど、
エフェクトがないのも必要という場合には、Componentを2つに分割する事で変更内容を1ファイルに閉じ込める事ができます。

おわり

今回はAtomicDesignで私がやらかした勘違いと失敗を、どのようにルールを見直した修正したかを記事にしてみました。
割とAtomicDesignの解説記事では、Moleculesからの作り方が多く書かれていますが、
Atomsでどうやって作るの?て記事はなかなか見ないので今回ネタにしてみました。
(ついでに自分犯した失敗の反省も込めて)

実際の現場ではAtomsは作らず、VuetifyなどのComponentFrameworkを使う事も多いと思われますが、
いざ自分でつくろうとすると案外どうやるんだったかな?とか、これでよかったよね?となりやすい部分であるので、
しっかりルール作りや方針確認をしたほうがいいですね!

また、アプリやサイトのデザインにがっつり影響する部分でもあるので
やっぱり自分で作ってると楽しいし、これからもたくさんAtomsを作っていこうかなと確信しました。
でも作りすぎるとImportがめんどくさいので、まとめて読み込む処理を組み入れなくちゃ…(確信)

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