和風なサイトのCSSの組み方

2021-10-19

もともと和系のデザインが好きで、過去何度か和風なサイトデザインに挑戦したことがあったのですが。

当時は自身の技術力もうそうなのですが、HTML や CSS も発達が追いついておらず、組むことを諦めてしまいました。

とはいえ令和の時代にもなれば、かなりスムーズに和風なサイトを組むことができるようになっています。

ということで、今日は和風なサイトの組み方を書いていこうと思います。


前提

今回は【縦書き】かつ【右から左】へスクロールするサイトを作っていこうと思います。

組み方

まずサイト全体の方向を設定します。

:root {
  direction: rtl;
}

次に文字を含む要素単位で、方向のリセットを行うと同時に、縦書きを設定します。

.hoge {
  direction: ltr;
  writing-mode: vertical-rl;
}

ここで direction をリセットしてあげないと、要素が下寄せになるので注意です。

また writing-mode をグローバルに当ててしまうと、flexgrid の方向が崩れるので、なるべく小さい要素単位で当てるようにしましょう。

基本的には上記の 2 つの設定で対応できます。

組む際の注意点

縦書きの場合 letter-spacingline-height の上下左右の方向が変わるので気をつけましょう。

フォームについて

inputtextareabutton など、フォーム周りのタグついては writing-mode を対応させることができません。

ただし button については比較的簡単に対処することが可能です。

<button>
  <span class="hoge"> fuga </span>
</button>

問題は文字の入力系なのですが、こちらは contenteditable というプロパティを使うことで対処が可能です。

MDN

自分は今回 react-contenteditable というパッケージを使って実装してみました。

実装イメージはこんな感じです。

import React, { useCallback } from "react";
import ContentEditable, { Props } from "react-contenteditable";
import { SubmitHandler, useForm } from "react-hook-form";
import striptags from "striptags";
import styles from "./style.module.scss";

type FieldValues = {
  hoge: string,
};

export type ContactTopProps = {
  onSubmit: SubmitHandler<FieldValues>,
};

function Form({ onSubmit }: FormProps): JSX.Element {
  const {
    formState: { errors },
    handleSubmit,
    register,
    setValue,
    watch,
  } = useForm <
  FieldValues >
  {
    defaultValues: {
      hoge: "",
    },
  };
  const handleChange =
    useCallback <
    Props["onChange"] >
    (({ currentTarget: { id }, target: { value } }) => {
      // setValue(id, striptags(value));
      setValue(id, value);
    },
    [setValue]);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <ContentEditable
        {...register("hoge")}
        className={styles.fuga}
        contentEditable={true}
        html={watch("hoge")}
        id="hoge"
        onChange={handleChange}
      />
      <button type="submit">
        <span className={styles.piyo}>Submit</span>
      </button>
    </form>
  );
}

export default Form;

注意点としては、contenteditable を使った場合、値に HTML が格納されてしまいます。

そのため striptags などを使用して、HTML のエスケープが必要になるケースもあるかなと。

今回はエスケープを onChange のタイミングで行っていますが、onSubmit のタイミングなどでも良いかもですね。

バリデーションチェックとの兼ね合い次第かなと。


ということで、和風なサイトを作る際のコツについて書いてみました。

実際すでにサイトを 1 つ作り上げたのですが、なかなかどうしてトリッキーな実装になってしまいます。

とはいえ、10 年前と比べたら実装の容易さは雲泥の差ですね、良い時代になったなぁと。

あとフォーム周りも組めるようになっていたのには驚きました。

contenteditable がユニークでおもしろいなぁと。

一応 Mac と Android、iOS の主要ブラウザでの正常動作が確認できているので、業務系もある程度問題なく通用しそうです。

ぜひ皆さんも組んでみてはいかがでしょうか。