独学者Fossa

独学していることなど

UIkit hook mixin 考察

UIkit3
UIkit3

使用環境

Name Version
Dart Sass 1.70.0
UIkit 3.17.11

前書き

UIkitをこよなく愛するFossaです(笑)

UIkitでは、mixinhookするために使っています。

例えば、下記の通りです。

.uk-alert {
    position: relative;
    margin-bottom: $alert-margin-vertical;
    padding: $alert-padding $alert-padding-right $alert-padding $alert-padding;
    background: $alert-background;
    color: $alert-color;
    @if(mixin-exists(hook-alert)) {@include hook-alert();}
}

hook-alertというmixinが存在していれば、hook-alertincludeします。

例えば、.uk-alertborder-radiusを追加したい場合は、下記の通りです。

@mixin hook-alert() {
  border-radius: 0.25rem;
}

生成されたCSSは、下記の通りです。

.uk-alert {
  position: relative;
  margin-bottom: 20px;
  padding: 15px 29px 15px 15px;
  background: #f3f4f6;
  color: #4b5563;
  border-radius: 0.25rem;
}

@use@forwardを使った場合、実現できるのか試してみました。

準備

scssディレクトリ配下に、下記のディレクトリとファイルを作ります。

種類 説明
File main.scss
Directory uikit オリジナル用
File uikit/mixins.scss
Directory uikit/components
File uikit/components/_index.scss
File uikit/components/alert.scss
Directory theme/mixins カスタムテーマ用
File theme/mixins/alert.scss

scss/main.scss

@use './uikit/components';

scss/uikit/mixins.scss

uikit/src/scss/mixins.scssをコピーしてください。

scss/uikit/components/_index.scss

@forward './alert';

scss/uikit/components/alert.scss

中身は、uikit/src/scss/components/alert.scssです。

一部だけ記載しますが、下記のように、記述します。

@use '../mixins' as original;
@use '../../theme/mixins/alert' as custom;

.uk-alert {
  position: relative;
  margin-bottom: $alert-margin-vertical;
  padding: $alert-padding $alert-padding-right $alert-padding $alert-padding;
  background: $alert-background;
  color: $alert-color;

  @if (mixin-exists("hook-alert", "custom")) {
    @include custom.hook-alert();
  }

  @else if (mixin-exists("hook-alert", "original")) {
    @include original.hook-alert();
  }
}

上記は説明のため、それぞれ3行使ってます。

実際は下記の通り、1行ずつ記述しています。

  @if (mixin-exists("hook-alert", "custom")) { @include custom.hook-alert(); }
  @else if (mixin-exists("hook-alert", "original")) { @include original.hook-alert(); }

scss/theme/mixins/alert.scss

@mixin hook-alert() {
  border-radius: 0.25rem;
}

本題

カスタムテーマ用のディレクトリの位置は、定めた位置になるので、仕様にするしかないです。

カスタムテーマ用のmixinが存在すれば、カスタムテーマ用のmixinincludeします。

カスタムテーマ用のmixinが存在しなくても、オリジナル用のmixinが存在すれば・・・としなければ、内容が重複します。

@importのように、Sass variablesは、オリジナルより先に読み込んで、mixinは、オリジナルより後で読み込むというやり方は、出来ません。

結果

sass --no-source-map --quiet --style expanded scss/main.scss:public/css/style.css
.uk-alert {
  position: relative;
  margin-bottom: 20px;
  padding: 15px 29px 15px 15px;
  background: #f3f4f6;
  color: #4b5563;
  border-radius: 0.25rem;
}

結論

UIkitの場合は、LessからSCSSにコンバートしているので、そのロジックを書き直せば、実現可能だと思います。

実現可能だけど、「UIkitは、Lessで使うのが無難かな?」と思いました。

もし、Sass@importが使えなくなったら、「PostCSSを使う方法もあるのかな?」と思います。*1

Variablesの件は、UIkit hook mixin 考察 (2) - 独学者Fossaに続きます。

後書き

日本語の記事では、私が知りたいことは、Googleで検索しても簡単には見つからず、ようやく言及している記事を見つけました。


追記(2024-02-04)

kojika17.com


CSS Frameworkのソースを覗いてみると、functionSass variablesを使って、Sass variablesfunctionを使っています。

@importから、@use@forwardに置き換えると、loopします。

上記で紹介した記事にも、loopするトラブルに遭遇したことは書いてありますが、解決方法は書いてありません。

トラブルに遭遇したことを書いている日本語の記事自体、ほとんど見つかりません。

もちろん、暫定的に解決したのですが、レポジトリがarchivedされたので、更新されることはないでしょう。

もし更新される機会があったら、もっとスマートな解決方法を実装されたような気がして、気になります。

追記(2024-02-17)

Inverseを使うのであれば、uikit/src/scss/mixins.scssと同等のtheme/mixins.scssを作成します。

@use '../../theme/mixins' as custom;に変更すれば、Inverseが使えるはずです。

Inverseは、mixinの中でmixinincludeしているので、ちょっとややこしいですね。

*1:或いは、Stylus?