stylesからdart-sassに変更した時に行なったこと・コード
stylusからdart-sassに変更したので、その時に対応したこと、stylusとscssのコードの比較に載せたものになります。
変更した箇所のコードについては以下になります。 github.com
stylusからdart-sassに変更した理由
- stylintでstylusのインデント調整した後に編集を行うとエラーになるので、修正がつらい
- 最近現場でもdart-sassを使う機会が増えたので、sassの勉強をしたい
- stylusの方はあまり開発が進んでいないので、stylusを使う機会が減りそう。。
※ 画像は2021年8月7日時点
scssで使用したライブラリ
1. node-sass-glob-importer
scssで@import: 'scss/**/*.scss';
のように記載を行うとまとめて読み込みを行なってくれるライブラリ
2. stylelint
scssの設定など
3. sass
dart-sassを使用するためのパッケージ
scss, stylusのコード
ディレクトリ
styluys
❯ tree . ├── foundation │ ├── _debug.styl │ ├── _default.styl │ ├── _reset.styl │ ├── barba │ │ └── _animation.styl │ ├── mixins │ │ ├── _MixinFontSize.styl │ │ ├── _MixinHoverAction.styl │ │ ├── _MixinWrapperWidth.styl │ │ └── _mediaquery.styl │ └── variables │ ├── _breakpoint.styl │ ├── _color.styl │ ├── _font.styl │ └── _zindex.styl ├── layout │ ├── _footer.styl │ └── _header.styl ├── object │ ├── components │ │ └── _text.styl │ ├── project │ │ └── _top.styl │ └── utility │ └── _device.styl └── style.styl
scss
❯ tree . ├── foundation │ ├── _debug.scss │ ├── _default.scss │ ├── _reset.scss │ ├── barba │ │ └── _animation.scss │ ├── mixins │ │ ├── _MixinFontSize.scss │ │ ├── _MixinHoverAction.scss │ │ ├── _MixinWrapperWidth.scss │ │ └── _mediaquery.scss │ └── variables │ ├── _breakpoint.scss │ ├── _color.scss │ ├── _font.scss │ └── _zindex.scss ├── layout │ ├── _footer.scss │ └── _header.scss ├── object │ ├── components │ │ └── _text.scss │ ├── project │ │ └── _top.scss │ └── utility │ └── _device.scss └── style.scss
コードの内容について
foundation/_debug
stylus
/* ** * * HTMLのセマンティックエラーを確認するためのcss * blog * https://ics.media/entry/200819/ * code * https://github.com/ics-creative/200819_debug_css/blob/master/docs/debug.css * */ @keyframes blink-red 0% outline-color red 49.9% outline-color red 50% outline-color transparent 100% outline-color transparent @keyframes blink-gold 0% outline-color gold 49.9% outline-color gold 50% outline-color transparent 100% outline-color transparent ul > :not(li) ol > :not(li) outline 2px solid red content '<ul>タグ、<ol>タグの直下に入れられるのは<li>タグだけです' animation blink-red 1s infinite dl > :not(dt):not(dd):not(div) outline 2px solid red content '<dl>タグ、タグの直下に入れられるのは<dt>,<dd>,および<div>タグだけです' animation blink-red 1s infinite a[name] outline 2px solid red content 'name属性はHTML5で廃止されました' animation blink-red 1s infinite a[href='javascript:void(0)'] outline 2px solid gold content '<a>タグは移動するためだけに使用するべきです' animation blink-gold 1s infinite a[target=_blank]:not([rel='noreferrer noopener']) outline 2px solid gold content 'target="_blank"の場合は悪用を防ぐためにもrel="noreferrer noopener"の使用を推奨します' animation blink-gold 1s infinite img:not([alt]) img[alt=''] display block outline 2px solid gold animation blink-gold 1s infinite img:not([width]) img[width=''] img:not([height]) img[height=''] display block outline 2px solid gold animation blink-gold 1s infinite :root iframe:nth-of-type(4) outline 2px solid gold content '連続して4つ以上のiframeが設置されています。iframeが複数あるとパフォーマンスに影響を与えます' animation blink-gold 1s infinite time:not([datetime]) time[datetime=''] outline 2px solid gold content 'datetime属性がない場合、タグ内に妥当な値が入力されていますか?' animation blink-gold 1s infinite time:not([datetime]) * time[datetime=''] * outline 2px solid red content 'datetime属性がない場合、タグ内に子孫要素をもってはいけません' animation blink-red 1s infinite font center frame blink marquee *[align] *[color] *[bgcolor] *[border] *[background] outline 2px solid red content '古いタグや属性が使用されています。古いタグの使用はやめ、装飾はCSSで行うようにしましょう' animation blink-red 1s infinite hgroup > :not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) outline 2px solid red content 'hgroupタグ内で許可されているのはh1~h6タグです' animation blink-red 1s infinite table > * ~ caption outline 2px solid red content 'capptionタグはtableタグの最初の子要素として配置しなくてはなりません' animation blink-red 1s infinite br + br display none
scss
/* ** * * HTMLのセマンティックエラーを確認するためのcss * blog * https://ics.media/entry/200819/ * code * https://github.com/ics-creative/200819_debug_css/blob/master/docs/debug.css * */ @keyframes blink-red { 0% { outline-color: red; } 49.9% { outline-color: red; } 50% { outline-color: transparent; } 100% { outline-color: transparent; } } @keyframes blink-gold { 0% { outline-color: gold; } 49.9% { outline-color: gold; } 50% { outline-color: transparent; } 100% { outline-color: transparent; } } ul > :not(li), ol > :not(li) { content: '<ul>タグ、<ol>タグの直下に入れられるのは<li>タグだけです'; outline: 2px solid red; animation: blink-red 1s infinite; } dl > :not(dt):not(dd):not(div) { content: '<dl>タグ、タグの直下に入れられるのは<dt>,<dd>,および<div>タグだけです'; outline: 2px solid red; animation: blink-red 1s infinite; } a[name] { content: 'name属性はHTML5で廃止されました'; outline: 2px solid red; animation: blink-red 1s infinite; } a[href='javascript:void(0)'] { content: '<a>タグは移動するためだけに使用するべきです'; outline: 2px solid gold; animation: blink-gold 1s infinite; } a[target='_blank']:not([rel='noreferrer noopener']) { content: 'target="_blank"の場合は悪用を防ぐためにもrel="noreferrer noopener"の使用を推奨します'; outline: 2px solid gold; animation: blink-gold 1s infinite; } img:not([alt]), img[alt=''] { display: block; outline: 2px solid gold; animation: blink-gold 1s infinite; } img:not([width]), img[width=''], img:not([height]), img[height=''] { display: block; outline: 2px solid gold; animation: blink-gold 1s infinite; } :root iframe:nth-of-type(4) { content: '連続して4つ以上のiframeが設置されています。iframeが複数あるとパフォーマンスに影響を与えます'; outline: 2px solid gold; animation: blink-gold 1s infinite; } time:not([datetime]), time[datetime=''] { content: 'datetime属性がない場合、タグ内に妥当な値が入力されていますか?'; outline: 2px solid gold; animation: blink-gold 1s infinite; } time:not([datetime]) *, time[datetime=''] * { content: 'datetime属性がない場合、タグ内に子孫要素をもってはいけません'; outline: 2px solid red; animation: blink-red 1s infinite; } font, center, frame, blink, marquee, *[align], *[color], *[bgcolor], *[border], *[background] { content: '古いタグや属性が使用されています。古いタグの使用はやめ、装飾はCSSで行うようにしましょう'; outline: 2px solid red; animation: blink-red 1s infinite; } hgroup > :not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) { content: 'hgroupタグ内で許可されているのはh1~h6タグです'; outline: 2px solid red; animation: blink-red 1s infinite; } table > * ~ caption { content: 'capptionタグはtableタグの最初の子要素として配置しなくてはなりません'; outline: 2px solid red; animation: blink-red 1s infinite; } br + br { display: none; }
foundation/_default
stylus
html body background MixinColorPalette(back) body color MixinColorPalette(text) font-size (16 / FontSize_Default) * 100% font-family FontFamily_Default text-rendering optimizeLegibility button cursor pointer a color inherit text-decoration none main display block min-width 375px // viewport-extra検証用のため、仮追加 height 200vh // スクロールするため、仮追加 [data-whatinput='mouse'] *:focus [data-whatinput='touch'] *:focus outline none
scss
@use "sass:math"; html, body { background: MixinColorPalette('back'); background: #fff; } body { color: MixinColorPalette(text); font-size: percentage(math.div(16, $FontSize_Default)); font-family: $FontFamily_Default; text-rendering: optimizeLegibility; } button { cursor: pointer; } a { color: inherit; text-decoration: none; } main { display: block; min-width: 375px; // viewport-extra検証用のため、仮追加 height: 200vh; // スクロールするため、仮追加 } [data-whatinput='mouse'] *:focus, [data-whatinput='touch'] *:focus { outline: none; }
foundation/_reset
stylus
* *::before *::after box-sizing border-box ul ol padding 0 list-style none body h1 h2 h3 h4 p ul ol li figure figcaption blockquote dl dd margin 0 body line-height 1.5 scroll-behavior smooth text-rendering optimizeSpeed a:not([class]) text-decoration-skip-ink auto img display block max-width 100% article > * + * margin-top 1em input button textarea select margin 0 padding 0 border none border-radius 0 background none background-color transparent color inherit font inherit appearance none // @stylint off @media (prefers-reduced-motion reduce) * transition-duration .01ms !important animation-duration .01ms !important animation-iteration-count 1 !important scroll-behavior auto !important
scss
*, *::before, *::after { box-sizing: border-box; } ul, ol { padding: 0; list-style: none; } body, h1, h2, h3, h4, p, ul, ol, li, figure, figcaption, blockquote, dl, dd { margin: 0; } body { line-height: 1.5; scroll-behavior: smooth; text-rendering: optimizeSpeed; } a:not([class]) { text-decoration-skip-ink: auto; } img { display: block; max-width: 100%; } article > * + * { margin-top: 1em; } input, button, textarea, select { padding: 0; margin: 0; font: inherit; color: inherit; background: none; background-color: transparent; border: none; border-radius: 0; appearance: none; } @media (prefers-reduced-motion: reduce) { * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; } }
barba/_animation
stylus
.barba-leave-active .barba-enter-active transition opacity .4s ease .barba-leave opacity 1 .barba-enter opacity 0 .barba-leave-to opacity 0 .barba-enter-to opacity 1
scss
.barba-leave-active, .barba-enter-active { transition: opacity 0.4s ease; } .barba-leave { opacity: 1; } .barba-enter { opacity: 0; } .barba-leave-to { opacity: 0; } .barba-enter-to { opacity: 1; }
mixins/_MixinFontSize
stylus
MixinFontSize(font, lineheight = defaule) Mixinfont = (font / FontSize_Default) if (lineheight == defaule) Mixinlineheight = 1.6666 else if (lineheight == normal) Mixinlineheight = normal else Mixinlineheight = (lineheight / font) font-size Mixinfont rem line-height Mixinlineheight
scss
@use "sass:math"; @mixin MixinFontSize($fontSize, $lineheight: 'default') { $Mixinfont: math.div($fontSize, $FontSize_Default); $Mixinlineheigh: 1.6666; @if $lineheight == 'default' { $Mixinlineheigh: 1.6666; } @else if $lineheight == 'normal' { $Mixinlineheigh: 'normal'; } @else { $Mixinlineheigh: math.div($lineheight, $fontSize); } font-size: #{$Mixinfont}rem; line-height: #{$Mixinlineheigh}; }
mixins/_MixinHoverAction
stylus
MixinHoverAction(hoverTime = 0) @media (hover hover) &:hover transition hoverTime s {block} @media all and (-ms-high-contrast none) &:hover transition hoverTime s {block} &:active {block}
scss
@mixin MixinHoverAction($hoverTime: 0) { @media (hover: hover) { &:hover { transition: #{$hoverTime}s; @content; } } @media all and (-ms-high-contrast: none) { &:hover { transition: #{$hoverTime}s; @content; } } &:active { @content; } }
mixins/_MixinWrapperWidth
stylus
MixinWrapperWidth(contentwidth, globalwidth = MixinBreakPoint(MAXPC), position = center) if (globalwidth == full) max-width 100% width percentage((contentwidth / MixinBreakPoint(MAXPC))) else max-width contentwidth width percentage((contentwidth / globalwidth)) if (position == center) margin-right auto margin-left auto else if (position == left) margin-right auto else if (positon == right) margin-left auto +sp-only() if (globalwidth == MixinBreakPoint(MAXPC) || (globalwidth == full)) width calc(100% - 40px) else width 100%
scss
@use "sass:math"; @mixin MixinWrapperWidth($contentwidth, $globalwidth: 1920, $position: center) { @if $globalwidth == 'full' { width: percentage(math.div($contentwidth, 1920)); max-width: 100%; } @else { width: percentage(math.div($contentwidth, $globalwidth)); max-width: $contentwidth; } @if $position == 'center' { margin-right: auto; margin-left: auto; } @else if $position == 'left' { margin-right: auto; } @else if $position == 'right' { margin-left: auto; } @include sp-only() { @if $globalwidth == MixinBreakPoint('MAXPC') or $globalwidth == 'full' { width: calc(100% - 40px); } @else { width: 100%; } } }
mixins/_mediaquery
stylus
// pcの最大幅(1920px)になったら max-pc() @media screen and (min-width MixinBreakPoint(MAXPC)) {block} // 通常のpc用(1560px以下) normal-pc() @media screen and (max-width MixinBreakPoint(PC_CONTENT)) {block} // 通常のpc用(1280px以下) min-pc() @media screen and (max-width MixinBreakPoint(PC)) {block} // 通常のpcとspの切り替え(pc用) pc-only() @media screen and (min-width MixinBreakPoint(TABLET)) {block} // 通常のpcとspの切り替え(sp用) sp-only() @media screen and (max-width MixinBreakPoint(TABLET)) {block} // スマートフォンのみ別で対応したい場合(767px以下) min-sp() @media screen and (max-width MixinBreakPoint(SMARTPHONE)) {block} // iphone5のみ別で対応したい場合 iphone5() @media screen and (max-width MixinBreakPoint(SMALL)) {block} // カスタムブレイクポイント custom-breakpoint(value, maxmin = max) if (maxmin == sp || max) maxmin = max else if (manmin == pc || min) maxmin = min @media screen and ({maxmin}-width value px) {block}
scss
// pcの最大幅(1920px)になったら @mixin max-pc() { @media screen and (min-width: MixinBreakPoint('MAXPC')) { @content; } } // 通常のpc用(1560px以下) @mixin normal-pc() { @media screen and (min-width: MixinBreakPoint('PC_CONTENT')) { @content; } } // 通常のpc用(1280px以下) @mixin min-pc() { @media screen and (min-width: MixinBreakPoint('PC')) { @content; } } // 通常のpcとspの切り替え(pc用) @mixin pc-only() { @media screen and (min-width: MixinBreakPoint('TABLET')) { @content; } } // 通常のpcとspの切り替え(sp用) @mixin sp-only() { @media screen and (max-width: MixinBreakPoint('TABLET')) { @content; } } // スマートフォンのみ別で対応したい場合(767px以下) @mixin min-sp() { @media screen and (max-width: MixinBreakPoint('SMARTPHONE')) { @content; } } // iphone5のみ別で対応したい場合 @mixin iphone5() { @media screen and (max-width: MixinBreakPoint('SMALL')) { @content; } } // カスタムブレイクポイント @mixin custom-breakpoint($value, $maxmin: 'max') { @if $maxmin == 'max' { $maxmin: 'max'; } @else { $maxmin: 'min'; } @media screen and (#{$maxmin}-width: #{$value}px) { @content; } }
variables/_breakpoint
stylus
BREAK_POINT = { MAXPC: 1920, PC_CONTENT: 1560, PC: 1280, TABLET: 1023, SMARTPHONE: 767, SMALL: 320 } BREAK_POINT_CUSTOM = 1180 MixinBreakPoint(deviceSize) return (BREAK_POINT[deviceSize]) px
scss
$BREAK_POINT: ( MAXPC: 1920, PC_CONTENT: 1560, PC: 1280, TABLET: 1023, SMARTPHONE: 767, SMALL: 320, ); $BREAK_POINT_CUSTOM: 1180; @function MixinBreakPoint($deviceSize) { @return map-get($BREAK_POINT, $deviceSize) + 'px'; }
variables/_color
stylus
COLOR_Palette = { default: { back: #fff, text: #333 }, footer: { text: #ddd } } MixinColorPalette(type, pattern = default) return COLOR_Palette[pattern][type]
scss
$COLOR_Palette: ( default: ( back: #fff, text: #333, ), footer: ( text: #ddd, ), ); @function MixinColorPalette($type, $pattern: 'default') { $object: map-get($COLOR_Palette, $pattern); @return map-get($object, $type); }
variables/_font
stylus
FontSize_Default = 16 FontFamily_Default = 'Helvetica Neue', Arial, 'Hiragino Kaku Gothic ProN', 'Hiragino Sans', Meiryo, sans-serif
scss
$FontSize_Default: 16; $FontFamily_Default: 'Helvetica Neue', Arial, 'Hiragino Kaku Gothic ProN', 'Hiragino Sans', Meiryo, sans-serif;
variables/_zindex
stylus
Z_common = header navModel Z_top = mainMv mainKv mainKv2 Z_about = aboutMv aboutKv Z_allcontent = Z_top Z_about Z_common Z_backContent = -1 zIndex(name) zNumber = 0 if (name == 'back') return Z_backContent for contentAry in Z_allcontent for contentName in contentAry zNumber = zNumber + 1 if (contentName == name) return zNumber return false
scss
$Z_common: header, navModel; $Z_top: mainMv, mainKv, mainKv2; $Z_about: aboutMv, aboutKv; $Z_allcontent: $Z_top, $Z_about, $Z_common; $Z_backContent: -1; @function zIndex($name) { $zNumber: 0; @if $name == 'back' { @return $Z_backContent; } @each $contentAry in $Z_allcontent { @each $contentName in $contentAry { $zNumber: $zNumber + 1; @if $contentName == $name { @return $zNumber; } } } @return false; }
layout/_footer
stylus
small color MixinColorPalette(text, footer)
scss
small { color: MixinColorPalette('text', 'footer'); }
layout/_header
stylus
.l-header margin 0 auto width calc(100% - 40px) .l-header__Title color MixinColorPalette(text)
scss
.l-header { width: calc(100% - 40px); margin: 0 auto; } .l-header__Title { color: MixinColorPalette(text); }
object/components/_text
stylus
.c-text MixinFontSize 15
scss
.c-text { @include MixinFontSize(15); }
object/project/_top
stylus
.p-top z-index zIndex(header) display flex MixinWrapperWidth 1280px full MixinFontSize 14 40 +custom-breakpoint(1000) font-size 20px .img-back width 237px height 153px background url('/assets/img/sample.png') background-size cover
scss
.p-top { z-index: zIndex('header'); display: flex; @include MixinWrapperWidth(1280, 'full'); @include MixinFontSize(14, 40); @include custom-breakpoint(1000) { font-size: 20px; } } .img-back { width: 237px; height: 153px; background: url('/assets/img/sample.png'); background-size: cover; }
object/utility/_device
stylus
.u-is-pc +sp-only() display none !important .u-is-sp +pc-only() display none !important
scss
.u-is-pc { @include sp-only() { display: none !important; } } .u-is-sp { @include pc-only() { display: none !important; } }
style
stylus
// @import './foundation/_debug' @import './foundation/variables/*' @import './foundation/mixins/*' @import './foundation/_reset' @import './foundation/_default' @import './foundation/barba/*' @import './layout/*' @import './object/**/*'
scss
// @import './foundation/debug' @import './foundation/variables/*'; @import './foundation/mixins/*'; @import './foundation/reset'; @import './foundation/default'; @import './foundation/barba/*'; @import './layout/*'; @import './object/components/*'; @import './object/project/*'; @import './object/utility/*';