🖼️

SvelteでinputをCSSに反映する

2023/05/06に公開

やりたいこと

  • inputにオプションや数字などを入力してCSSの値を変化させたい

結論

  • js -> htmlタグのstyleプロパティでCSS variableを定義 -> CSS
  • mix-blend-modeの重なりを画面ポチポチで試すためのツール
    • 文字・マスクの色・mix-blend-modeのモード変更を選択できるようにする
mixBlendModeImg.svelte
<script lang="ts">
  import type { ImgOptions } from './type';

  export let imgSrc: string;
  export let text: ImgOptions;  // inputから入力される変数が入る
  export let mask: ImgOptions;  // inputから入力される変数が入る
</script>

<div
  class="root"
  style="
  --text-blend-mode: {text.blendMode}; 
  --text-top: {text.top}px; --text-left: {text.left}px; 
  --text-red: {text.red}; --text-green: {text.green}; --text-blue: {text.blue}; --text-alpha: {text.alpha}; 
  --text-z-index: {text.layer};
  --mask-blend-mode: {mask.blendMode}; 
  --mask-top: {mask.top}px; --mask-left: {mask.left}px; 
  --mask-red: {mask.red}; --mask-green: {mask.green}; --mask-blue: {mask.blue}; --mask-alpha: {mask.alpha};
  --mask-z-index: {mask.layer};"
>
  <div class="imgWrapper">
    <p class="text">Welcome</p>
    <img src={`https://source.unsplash.com/${imgSrc ? imgSrc : 'Ak81Vc-kCf4'}`} alt="画像" />
  </div>
</div>

<style lang="scss">
  .root {
    display: flex;
    justify-content: center;
    margin: 48px;
    margin-bottom: 500px;
    .imgWrapper {
      position: relative;
      margin: 24px;
      img {
        width: 500px;
      }
      .text {
        display: block;
        position: absolute;
        font-size: 88px;
        font-weight: 700;
        top: var(--text-top);
        left: var(--text-left);
        margin: 0;
        z-index: var(--text-z-index);
        line-height: 1;
        color: rgba(var(--text-red), var(--text-green), var(--text-blue), var(--text-alpha));
        mix-blend-mode: var(--text-blend-mode);
      }

      &::before {
        position: absolute;
        display: block;
        width: calc(100% + 48px);
        height: calc(100% + 48px);
        content: '';
        top: var(--mask-top);
        left: var(--mask-left);
        background: rgba(var(--mask-red), var(--mask-green), var(--mask-blue), var(--mask-alpha));
        z-index: var(--mask-z-index);
        mix-blend-mode: var(--mask-blend-mode);
      }
    }
  }
</style>

悩みポイント色々

HTMLで変数を宣言するので、CSSで『どこから使えるか』がわからなくなる

  • このファイルのHTMLのトップレベルで変数を宣言することで、このファイル内のCSSであれば呼び出せる、というたてつけにしている
  • CSSのスコープとしてはさらに狭くすることができるが、更に細かく分割する必要もないと思って見送り

styleプロパティでスタイリングするかどうか

  • 今回の場合はafter / beforeを利用しており、styleでスタイリングするとHTMLが見えづらくなりすぎてしまうため避けた
  • 変数が1つ、2つであればstyleタグ内の方が『CSS変数のtypo』と避けられるという点でメリットがあるかもしれない

CSS変数、補完が効きづらくてtypoしそう

  • 1度しか出てこないのでコピペ対処で目をつむった
  • 他の方法が本当にないのか、と思ったが、公式で紹介されている方法が上記の方法だったりする
  • なので出現回数や用途によってはstyleタグ内でスタイリングする方がオススメかもしれない

つぶやき

  • 正直いまいちしっくりきていない。私が知らないだけで、もう少し安心安全な方法があるのでは?という気持ちがとてもある。
  • svelteのシンタックスハイライト、tsを選ぶかhtmlを選ぶかcssを選ぶかでとても迷った。

Discussion