GatsbyJSにSemantic UIをカスタマイズして入れる

GatsbyJSにSemantic UIをカスタマイズして入れる

February 7th, 2019

当ブログにSemantic UIを使っていますが、そのまま使うと日本語フォントに対応していないようだったのでフォントを追加したりとのカスタマイズをしました。

導入からカスタマイズまでのログを残しておきます。 GatsbyJSを対象にしていますが、Webpackを使っているなら大きくは変わらないと思います。

GatsbyJSにSemantic UIを導入

単純にGatsbyJSにSemantic UIを導入するのは簡単でした。

Reactで構成されているのでSemantic UI Reactを追加するだけでOKでした。

$ yarn add semantic-ui-css semantic-ui-react

これではThemeが反映されないので、gatsby-browser.jsファイルを作成し、下記のようにThemeを読み込みます。 gatsby-broswer.jsの設定はこちらを参照してください。

require('semantic-ui-css/semantic.min.css')

これでConatinerLayoutなどSemantic UI Reactのコンポーネントを使えます。

import { Segment, Container } from 'semantic-ui-react'

const TestComponent = () => (
    <Container>
        <Segment>
            <p>{'hoge'}</p>
        </Segment>
    </Container>
)

Semantic UIをカスタマイズ

カスタマイズ方法を調べるとSemantic-UI-LESSを使いカスタマイズするように出てきます。

少し古いですが次の記事を参考にしました。

Webpack 2 & Semantic UI Theming - webmonkeys - Medium

Because there are a lot of icons & images, you must make sure that your webpack configuration know's how to bundle them. An example configuration that you should follow if you don't have anything set up, would be the following: Which would of course depend on the url-loader and file-loader loaders of Webpack.

※今回作成するテーマは custom-semantic-theme という名前になります。自身で別名にする場合は読み替えてください。

準備

Semantic-UI-LESSがないとはじまりません。追加してあげましょう。

$ yarn add emantic-ui-less

さらに自作テーマのディレクトリも作成し、必要ファイルをコピーします。

$ mkdir -p custom-semantic-theme/site
$ cp node_modules/semantic-ui-less/theme.config.example custom-semantic-theme/theme.config
$ cp node_modules/semantic-ui-less/theme.less custom-semantic-theme/semantic.less

theme.config 編集

custom-semantic-theme/theme.configには下記の変更が必要です。

  1. @import "theme.less"; -> @import "~semantic-ui-less/theme.less";
  2. @siteFolder : "site"; -> @siteFolder : "../../custom-semantic-theme/site";
  3. @fontPath : "../../../themes/@{theme}/assets/fonts"; を最終行に追加

最終的にtheme.configは次のようになります。

/*

████████╗██╗  ██╗███████╗███╗   ███╗███████╗███████╗
╚══██╔══╝██║  ██║██╔════╝████╗ ████║██╔════╝██╔════╝
   ██║   ███████║█████╗  ██╔████╔██║█████╗  ███████╗
   ██║   ██╔══██║██╔══╝  ██║╚██╔╝██║██╔══╝  ╚════██║
   ██║   ██║  ██║███████╗██║ ╚═╝ ██║███████╗███████║
   ╚═╝   ╚═╝  ╚═╝╚══════╝╚═╝     ╚═╝╚══════╝╚══════╝

*/

/*******************************
        Theme Selection
*******************************/

/* To override a theme for an individual element
   specify theme name below
*/

/* Global */
@site        : 'default';
@reset       : 'default';

/* Elements */
@button      : 'default';
@container   : 'default';
@divider     : 'default';
@flag        : 'default';
@header      : 'default';
@icon        : 'default';
@image       : 'default';
@input       : 'default';
@label       : 'default';
@list        : 'default';
@loader      : 'default';
@placeholder : 'default';
@rail        : 'default';
@reveal      : 'default';
@segment     : 'default';
@step        : 'default';

/* Collections */
@breadcrumb  : 'default';
@form        : 'default';
@grid        : 'default';
@menu        : 'default';
@message     : 'default';
@table       : 'default';

/* Modules */
@accordion   : 'default';
@checkbox    : 'default';
@dimmer      : 'default';
@dropdown    : 'default';
@embed       : 'default';
@modal       : 'default';
@nag         : 'default';
@popup       : 'default';
@progress    : 'default';
@rating      : 'default';
@search      : 'default';
@shape       : 'default';
@sidebar     : 'default';
@sticky      : 'default';
@tab         : 'default';
@transition  : 'default';

/* Views */
@ad          : 'default';
@card        : 'default';
@comment     : 'default';
@feed        : 'default';
@item        : 'default';
@statistic   : 'default';

/*******************************
            Folders
*******************************/

/* Path to theme packages */
@themesFolder : 'themes';

/* Path to site override folder */
@siteFolder  : '../../custom-semantic-theme/site';


/*******************************
         Import Theme
*******************************/

@import (multiple) '~semantic-ui-less/theme.less';

@fontPath : "../../../themes/@{theme}/assets/fonts";

/* End Config */

semantic.less 編集

こちらでは必要なElementの読み込みを行っているようです。必要なものだけ読み込むのがいいでしょう。 不要なものを削除したら下記のようにリプレースを行います。

& { @import "definitions/..." -> & { @import "~semantic-ui-less/definitions/..."

今回はすべてのコンポーネントを参照するようにしました。結果は次のようになります。

/*

███████╗███████╗███╗   ███╗ █████╗ ███╗   ██╗████████╗██╗ ██████╗    ██╗   ██╗██╗
██╔════╝██╔════╝████╗ ████║██╔══██╗████╗  ██║╚══██╔══╝██║██╔════╝    ██║   ██║██║
███████╗█████╗  ██╔████╔██║███████║██╔██╗ ██║   ██║   ██║██║         ██║   ██║██║
╚════██║██╔══╝  ██║╚██╔╝██║██╔══██║██║╚██╗██║   ██║   ██║██║         ██║   ██║██║
███████║███████╗██║ ╚═╝ ██║██║  ██║██║ ╚████║   ██║   ██║╚██████╗    ╚██████╔╝██║
╚══════╝╚══════╝╚═╝     ╚═╝╚═╝  ╚═╝╚═╝  ╚═══╝   ╚═╝   ╚═╝ ╚═════╝     ╚═════╝ ╚═╝

  Import this file into your LESS project to use Semantic UI without build tools
*/

/* Global */
& { @import "~semantic-ui-less/definitions/globals/reset"; }
& { @import "~semantic-ui-less/definitions/globals/site"; }

/* Elements */
& { @import "~semantic-ui-less/definitions/elements/button"; }
& { @import "~semantic-ui-less/definitions/elements/container"; }
& { @import "~semantic-ui-less/definitions/elements/divider"; }
& { @import "~semantic-ui-less/definitions/elements/flag"; }
& { @import "~semantic-ui-less/definitions/elements/header"; }
& { @import "~semantic-ui-less/definitions/elements/icon"; }
& { @import "~semantic-ui-less/definitions/elements/image"; }
& { @import "~semantic-ui-less/definitions/elements/input"; }
& { @import "~semantic-ui-less/definitions/elements/label"; }
& { @import "~semantic-ui-less/definitions/elements/list"; }
& { @import "~semantic-ui-less/definitions/elements/loader"; }
& { @import "~semantic-ui-less/definitions/elements/placeholder"; }
& { @import "~semantic-ui-less/definitions/elements/rail"; }
& { @import "~semantic-ui-less/definitions/elements/reveal"; }
& { @import "~semantic-ui-less/definitions/elements/segment"; }
& { @import "~semantic-ui-less/definitions/elements/step"; }

/* Collections */
& { @import "~semantic-ui-less/definitions/collections/breadcrumb"; }
& { @import "~semantic-ui-less/definitions/collections/form"; }
& { @import "~semantic-ui-less/definitions/collections/grid"; }
& { @import "~semantic-ui-less/definitions/collections/menu"; }
& { @import "~semantic-ui-less/definitions/collections/message"; }
& { @import "~semantic-ui-less/definitions/collections/table"; }

/* Views */
& { @import "~semantic-ui-less/definitions/views/ad"; }
& { @import "~semantic-ui-less/definitions/views/card"; }
& { @import "~semantic-ui-less/definitions/views/comment"; }
& { @import "~semantic-ui-less/definitions/views/feed"; }
& { @import "~semantic-ui-less/definitions/views/item"; }
& { @import "~semantic-ui-less/definitions/views/statistic"; }

/* Modules */
& { @import "~semantic-ui-less/definitions/modules/accordion"; }
& { @import "~semantic-ui-less/definitions/modules/checkbox"; }
& { @import "~semantic-ui-less/definitions/modules/dimmer"; }
& { @import "~semantic-ui-less/definitions/modules/dropdown"; }
& { @import "~semantic-ui-less/definitions/modules/embed"; }
& { @import "~semantic-ui-less/definitions/modules/modal"; }
& { @import "~semantic-ui-less/definitions/modules/nag"; }
& { @import "~semantic-ui-less/definitions/modules/popup"; }
& { @import "~semantic-ui-less/definitions/modules/progress"; }
& { @import "~semantic-ui-less/definitions/modules/rating"; }
& { @import "~semantic-ui-less/definitions/modules/search"; }
& { @import "~semantic-ui-less/definitions/modules/shape"; }
& { @import "~semantic-ui-less/definitions/modules/sidebar"; }
& { @import "~semantic-ui-less/definitions/modules/sticky"; }
& { @import "~semantic-ui-less/definitions/modules/tab"; }
& { @import "~semantic-ui-less/definitions/modules/transition"; }

カスタマイズ部分を作成

ここまででベースの部分は完了です。あとはカスタマイズするだけです。 今回は日本語フォント(Noto Sans JP)を使うようにします。

カスタマイズはSemantic-UI-LESSリポジトリのthemesを参考にしました。

まずは必要となるファイルを作成します。

$ mkdir custom-semantic-theme/site/globals
$ touch custom-semantic-theme/site/globals/site.variables 

globals/site.variablesにはファイルが示すとおりサイト全体で使うような変数を設定します。 material Themeを参考に次のようにしました。

/*-------------------
       Fonts
--------------------*/

@headerFont        : 'Noto Sans JP', 'Helvetica Neue', Arial, Helvetica, sans-serif;
@pageFont          : 'Noto Sans JP', 'Helvetica Neue', Arial, Helvetica, sans-serif;
@googleFontName    : 'Noto Sans JP';

@googleFontName にフォント名(Google Fontsにあるもの)を指定すると勝手に取得してくれるようです。このあたりはSemanticUIのLESS本体をみるとわかると思います。

Webpack設定変更

最後にWebpackの設定です。

記事内ではwebpackを直で使う方法が記載されています。しかし、GatsbyJSはWebpackをWrapして隠蔽してあるので、GatsbyJSでWebpackの設定ファイルをいじる方法が必要になります。 検索をするとこちらがでてきます。ちょうLESSをいじるような例が載っていたのでこれを真似してgatsby-node.jsを編集してみます。

先程のカスタマイズの記事と合わせると下記のようになります。

exports.onCreateWebpackConfig = ({
                                   stage,
                                   rules,
                                   loaders,
                                   plugins,
                                   actions,
                                 }) => {
  actions.setWebpackConfig({
    resolve: {
      alias: {
        '../../theme.config$': path.join(__dirname, 'custom-semantic-theme/theme.config')
      }
    },
    module: {
      rules: [
        {
          test: /\.less$/,
          use: [
            loaders.miniCssExtract(),
            loaders.css({ importLoaders: 1 }),
            loaders.postcss(),
            `less-loader`,
          ],
        },
      ],
    },
    plugins: [],
  })
}

必要なモジュールがあるので追加します。

$ yarn add -D less css-loader less-loader

確認

ビルドして確認してみましょう。

$ gatsby build && gatsby serve

最後に

普段フロントをほとんど触らず、LESSなども怪しいですが表示することができました。 不備やわからないことがあったらTwitterなどでご連絡ください。

Share

Yohei icon
Yohei

Androidアプリを得意とする人。iOS, サーバーサイドもできる。 週2フリーランスとして活動中。

©MERCURY MAEDA