20190820のCSSに関する記事は2件です。

Svelteのコンポーネントを理解したくて『シュバババッ!』コンポーネントを作ってみた

こんにちは。ちょっと自分でもどこを目指しているのかわからない 1 あずきしろもち(@azukisiromochi) です。

今回は Svelte のコンポーネントの話。

前フリ

※ループさせていないので、右下の [Rerun] ボタンを押して試してみてください

See the Pen Syubababa!!! by あずきしろもち (@azukisiromochi) on CodePen.

CSSアニメーションを勉強しようと思ってこういうやつ作ったんです。

シュバババッ! 』って感じのやつ。
(あとで気づいたけど、右スクロールするとオブジェクト見えてるなw)

いま、ポートフォリオサイトを作成していて、モーダルをオープンするときのアニメーションに、この『 シュバババッ! 』を使ってみたいなーと思ったわけです。

どんなコンポーネントにするのか

そもそもコンポーネントって?

Svelte の公式リファレンスにはコンポーネントの定義が記載されていません(たぶん)。
SvelteVue.js に非常に近い構文ということもあって、そちらの定義を確認してみましょう。

小さく、自己完結的で、(多くの場合)再利用可能なインスタンスをコンポーネントという

キーワードは

  • 小さい
  • 自己完結的
  • 再利用可能

みたいですね。

『シュバババッ!』はどんなコンポーネントになるのか?

先程の CodePen のコードでは

<div class="syubababa a"></div>
<div class="syubababa b"></div>
<div class="syubababa c"></div>
<div class="syubababa d"></div>
<div class="syubababa e"></div>

こんな感じに <div> 要素が並んでいました。

つまり、5つの『 シュバッ 』が順々にアニメーションしているんです。
コンポーネントのキーワードにあった 再利用可能 に、非常によく当てはまると思いませんか?

ということで、この1つの『 シュバッ 』を Svelte のコンポーネントとして定義して進めてみましょう!

コンポーネントの仕様を明確にしよう!

コンポーネントは、1つの『 シュバッ 』の単位にすることは決めました。
ですが、ただこの『 シュバッ 』を並べるだけでは面白くありません。

シュバッ 』の 高さ を変えたり、 速度 を変えたり、 動き出すタイミング を変えたり……
このあたり(仕様)を明確にしていきます。

<div class="syubababa a"></div>
<div class="syubababa b"></div>
<div class="syubababa c"></div>
<div class="syubababa d"></div>
<div class="syubababa e"></div>

もう一度、このコードに戻ります。
それぞれの <div> に共通の .syubababa クラスと、個々の .a .b .c .d .e クラスがあります。

コンポーネント化に置き換えると、 .syubababa クラスがコンポーネントの共通仕様で、 .a .b .c .d .e クラスが動的に変動させることのできる要素になるでしょう。

例えば .a の場合、

.a {
  animation-duration: 800ms;
  animation-delay: 700ms;
}

と設定されていますし、 .d の場合、

.d {
  animation-delay: 1400ms;
  height: 10vh;
}

と設定されています。

コンポーネントの変動的な要素としては、次のようになりそうです。

animation-duration 仕様
animation-duration アニメーション一回分の時間の長さ ≒ 速度
animation-delay アニメーションの開始タイミング
height シュバッ 』の高さ

コンポーネントの単位では、

// Set style `animation-duration` (default: 800ms)
let duration = '';
// Set style `animation-delay` (default: 0)
let delay = '';
// Set style `height` (default: 15vh)
let height = '';

この3種類のプロパティーを扱って『 シュバッ 』を変動させていこうと思います。

コンポーネントを実装していく

ここまでで『 シュバババッ! 』は、『 シュバッ 』コンポーネントをいくつか並べて実現することを決めました。
また、『 シュバッ 』コンポーネントは、 duration delay height をプロパティに持ち、それぞれの『 シュバッ 』に個性を持たせることも決めました。

それでは順を追って Svelte のコンポーネントを実装していきましょう!

コンポーネントのファイルを作成する

components/Syubababa.svelte
<script>
  // JavaScript 書くところ
</script>

<style>
  /* CSS 書くところ */
</style>

<!-- html 書くところ -->
<div/>

.svelte ファイルの構造はこのようになっています。
Vue.js と非常によく似ていますが、 <template> タグはなく直接 html タグをコーディングする形になります。

コンポーネントの仕様により、実装する順序はまちまちですが、今回は『 シュバババッ! 』を作成した順序を一例として紹介したいと思います。

スタイルを適用させる

components/Syubababa.svelte
<script>
  // JavaScript 書くところ
</script>

<style lang="scss">
$color1: #e1315b;
$color2: #f47d4a;
$color3: #ffff42;
$color4: #00cffa;

div {
  background: $color1;
  height: 15vh;
  width: 10vw;
  margin-left: -15vw;
    animation-name: fadeIn;
  animation-duration: 800ms;
  animation-timing-function: ease;
  // animation-iteration-count: 1;
  animation-fill-mode:forwards;
}

@keyframes fadeIn {
  15% { background: $color1; }
    30% { background: $color2; }
    45% { background: $color3; }
  50% {
    transform: scaleX(15) skew(-30deg);
    transform-origin: 0% 50%;
  }
  75% { border-radius: 30% 20% / 40% 15%; }
    80% { background: $color4; }
  90% { box-shadow: -20px 10px 10px 10px rgba(0, 0, 0, .8); }
  100% {
    transform: translatex(120vw) scaleX(2) skew(0deg);
    transform-origin: 0% 50%;
    margin-left: 0;
  }
}
</style>

<!-- html 書くところ -->
<div/>

CodePen の実装を参考に CSS を設定しました。

SCSS を使ってしまっていますが、色を調整するための変数としてしか利用していません。
SvelteSapper で SCSS を使いたい人がいましたら こちら をどうぞ)

この状態でも『 シュバッ 』はコンポーネントとして動作します。

index.svelte
<script>
import Syubababa from '../components/Syubababa.svelte';
</script>

<style lang="scss">
</style>

<Syubababa/>

index.svelte<script> タグでコンポーネントを import し、タグとして <Syubababa/> をコーディングすると……
syuba.gif
と、個性のない(変動的な要素のない)『 シュバッ 』コンポーネントが出来上がりました!

続いて、個性を出していきましょう!

コンポーネントにプロパティを持たせる

components/Syubababa.svelte
<script>
  // Set style `animation-duration` (default: 800ms)
    export let duration = '';
  // Set style `animation-delay` (default: 0)
  export let delay = '';
  // Set style `height` (default: 15vh)
  export let height = '';
</script>

<script> タグだけ切り出しましたが、仕様のところで決めた3つの変動要素(変数)を export させています。
これで親コンポーネントから『 シュバッ 』コンポーネントにプロパティを設定し、個性を出すことができるようになります。

変数を export させたのはいいですが、実際の html に変動要素のスタイルを適用する必要があります。
今度は html 部分を見ていきましょう。

components/Syubababa.svelte
<div style="animation-duration: {duration}; animation-delay: {delay}; height: {height}"/>

<div> タグの style 要素に animation-duration animation-delay height を設定し、それぞれに対して、 <script> タグで宣言した変数を設定しています。
Vue.js の場合は {{ hoge }} でバインドしますが、 Svelte の場合は { hoge } でバインドします。

それでは、親コンポーネント( index.svelte )側からプロパティを設定してみましょう。

index.svelte
<script>
import Syubababa from '../components/Syubababa.svelte';
</script>

<style lang="scss">
</style>

<Syubababa duration={"800ms"} delay={"300ms"} height={"50vh"} />

<Syubababa/> コンポーネントの3つのプロパティを設定すると……
syuba2.gif
個性が出ましたね!

シュバババッ!

ここまでくれば、あとはコンポーネントを並べて『 シュバババッ! 』しましょう!

index.svelte
<script>
import Syubababa from '../components/Syubababa.svelte';
</script>

<style lang="scss">
</style>

<Syubababa duration={"800ms"} delay={"700ms"} />
<Syubababa duration={"700ms"} delay={"1000ms"} height={"30vh"} />
<Syubababa duration={"600ms"} delay={"1200ms"} height={"20vh"} />
<Syubababa delay={"1400ms"} height={"10vh"} />
<Syubababa delay={"1500ms"} height={"25vh"} />

syubababa!!!.gif

まとめ

Svelte のコンポーネントは Vue.js のものと非常に似ていて、 Vue.js を触ったことのある人ならすんなり使えるのではないでしょうか。
今回は紹介していませんが、 Svelte にも <slot> が用意されており、より自由度の高いコンポーネントが作れると思います。

両方とも使っている身としては、 Svelte の早さは魅力的で もっと流行ってほしいな― と思います。

みなさんも興味を持ったなら、ぜひ使ってみてくださいね :yum:


それではお別れは作成途中のポートフォリオサイトのモーダルアニメーションで~ :wave:

modal.gif


  1. 色の勉強をしてみたり、コード書いたり、絵を描いたり、小説を書いたり……。絶賛迷走中。 

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

cssだけでトグルを実装する

背景

WordPressのサイトを作っていて、ふとトグル(クリックしたら展開するやつ)を実装したいなと思ったんですが、そのためだけにJSを用意しないといけないのがめんどくさいなぁと思ったので、CSSだけで実装する方法を探しました。

次同じようなことする時に忘れていそうなので備忘録的に描いておくことにします。

コード

<!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>
    <style>
    #toggle1{
        display: none;
    }
    .toggle-inner{
        display: none;
    }
    #toggle1:checked ~ .toggle-inner{
        display: block;
    }
    </style>
</head>
<body>
    <input type="checkbox" id="toggle1">
    <div class="toggle-outer">
        <label for="toggle1">クリックして開く▼</label>
    </div>
    <div class="toggle-inner">
        <hr>
        <p>長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章</p>
    </div>
</body>
</html>

説明

  • checkbox(id:toggle1)、toggle-outer、toggle-innerという順番に要素を記述
    • toggle-outer:展開・折りたたみをしないエリア
    • toggle-inner:展開・折りたたみをするエリア
  • toggle-inner配下へ、展開後に表示するコンテンツを用意してdisplay:noneを当てておく
  • checkboxがチェックありの場合のみ、toggle-innerがdisplay:blockになるようにする
    • #toggle1:checked ~ .toggle-inner で「checkbox(チェック有り)の後ろにあるtoggle-inner」にだけスタイルを適用するという指定ができる(参考:E ~ F-CSS3リファレンス http://www.htmq.com/selector/precede.shtml)

スクショ

展開前

image.png

展開後

image.png

CodePen

See the Pen GRKjQwJ by Hiroaki Kato (@hirobel) on CodePen.

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