第5章 現場で使える実践Sassテクニック
5-2 レイアウト・パーツで使えるテクニック
clearfix をミックスインで活用する
@mixin clearfix {
&::after {
content: "";
display: block;
clear: both;
}
}
@mixin clearfix {
&::after {
content: "";
display: block;
clear: both;
}
}
.item {
background: #eee;
}
.item::after {
content: "";
display: block;
clear: both;
}
.item .image {
float: left;
width: 100px;
}
.item .text {
float: left;
}
変数を使って、サイドバーの幅を自動的に計算する
// 全体の幅
$wrap-width: 960px;
// メインエリアの幅
$main-width: 640px;
// サイドバーの幅
$side_width: $wrap_width - $main_width - 20;
#contents {
width: $wrap_width;
}
#main {
width: $main_width;
}
#side {
width: $side_width;
}
#contents {
width: 960px;
}
#main {
width: 640px;
}
#side {
width: 300px;
}
#side {
width: 294px;
}
nullで簡単に条件分岐をしてレイアウトをする
$height: false;
.item {
width: 500px;
@if $height {
height: $height;
}
}
.item {
width: 500px;
}
// 高さが必要な場合は値を単位付きで。不要な場合はnull。
$height: null;
.item {
width: 500px;
height: $height;
}
.item {
width: 500px;
}
@mixin itemBox ($width, $height, $margin:null, $padding:null) {
width: $width;
height: $height;
margin: $margin;
padding: $padding;
}
.itemA {
// 不要なプロパティはnull。
@include itemBox(100px, null, 10px, 20px);
}
.itemB {
@include itemBox(null, auto, 20px auto);
}
.itemA {
width: 100px;
margin: 10px;
padding: 20px;
}
.itemB {
height: auto;
margin: 20px auto;
}
$duration: null;
a {
transition: all $duration linear;
}
a {
transition: all linear;
}
calcとSassを組み合わせて四則演算を便利に使う
.item {
width: calc(100% - 1px * 2);
}
.item {
width: calc(100% - 1px * 2);
}
$border: 1px;
.item {
width: calc(100% - $border * 2);
}
.item {
width: calc(100% - $border * 2);
}
$border: 1px;
.item {
width: calc(100% - #{$border} * 2);
}
.item {
width: calc(100% - 1px * 2);
}
$border: 100px - 1px * 2;
.item {
width: calc(#{$border});
}
.item {
width: calc(98px);
}
$border: "100px - 1px * 2";
.item {
width: calc(#{$border});
}
.item {
width: calc(100px - 1px * 2);
}
$box: "100px - 1px * 2";
$contents: "100% - 20px";
.item {
width: calc(#{$contents} - #{$box});
}
.item {
width: calc(100% - 20px - 100px - 1px * 2);
}
@for を使って余白調整用のclassを生成する
$spaceClass: true !default;
$spacePadding: false !default;
$endValue: 10 !default;
@if $spaceClass {
@for $i from 0 through $space_endValue {
.mt#{$i * 5} {
margin-top: 5px * $i !important;
}
.mb#{$i * 5} {
margin-bottom: 5px * $i !important;
}
@if $spacePadding {
.pt#{$i * 5} {
padding-top: 5px * $i !important;
}
.pb#{$i * 5} {
padding-bottom: 5px * $i !important;
}
}
}
}
.mt0 {
margin-top: 0px !important;
}
.mb0 {
margin-bottom: 0px !important;
}
.mt5 {
margin-top: 5px !important;
}
.mb5 {
margin-bottom: 5px !important;
}
...(略)...
.mt50 {
margin-top: 50px !important;
}
.mb50 {
margin-bottom: 50px !important;
}
リストマーカー用の連番を使ったclass名を作成する
%markBase {
padding-left: 15px;
background-position: 0em .5em;
background-repeat: no-repeat;
}
@for $i from 1 through 3 {
.mark_#{$i} {
@extend %markBase;
background-image: url(../img/mark_#{$i}.png);
}
}
.mark_1, .mark_2, .mark_3 {
padding-left: 15px;
background-position: 0em .5em;
background-repeat: no-repeat;
}
.mark_1 {
background-image: url(../img/mark_1.png);
}
.mark_2 {
background-image: url(../img/mark_2.png);
}
.mark_3 {
background-image: url(../img/mark_3.png);
}
連番を使ったclass名のゼロパディング(0埋め)をする
$tmp: "";
@for $i from 1 through 15 {
@if $i < 10 {
$tmp: "0#{$i}";
} @else {
$tmp: $i;
}
.mark_#{$tmp} {
background-image: url(../img/mark_#{$tmp}.png);
}
}
.mark_01 {
background-image: url(../img/mark_01.png);
}
.mark_02 {
background-image: url(../img/mark_02.png);
}
...(略)...
.mark_14 {
background-image: url(../img/mark_14.png);
}
.mark_15 {
background-image: url(../img/mark_15.png);
}
文字リンクカラーのミックスインを作る
@mixin link-color($normal, $hover) {
color: $normal;
&:hover {
color: $hover;
text-decoration: none;
}
}
a {
@include link-color(#f00, #00f);
}
a {
color: red;
}
a:hover {
color: blue;
text-decoration: none;
}
$normal: #f00;
$hover: #00f;
@mixin link-color($n:$normal, $h:$hover) {
color: $n;
&:hover {
color: $h;
text-decoration: none;
}
}
a {
@include link-color;
}
a {
color: red;
}
a:hover {
color: blue;
text-decoration: none;
}
@mixin link-color2($n) {
color: $n;
&:hover {
color: lighten($n, 30%);
text-decoration: none;
}
}
a {
@include link-color2(#f00);
}
a {
color: red;
}
a:hover {
color: #ff9999;
text-decoration: none;
}
複数の値を@eachでループし、ページによって背景を変更する
$setBG: top, about, company, contact;
@each $i in $setBG {
.body-#{$i} {
background-image: url(../img/bg_#{$i}.png);
}
}
.body-top {
background-image: url(../img/bg_top.png);
}
.body-about {
background-image: url(../img/bg_about.png);
}
.body-company {
background-image: url(../img/bg_company.png);
}
.body-contact {
background-image: url(../img/bg_contact.png);
}
$setBG: top red, about blue, company green, contact yellow;
@each $i in $setBG {
.body-#{nth($i, 1)} {
background-image: url(../img/bg_#{nth($i, 2)}.png);
}
}
.body-top {
background-image: url(../img/bg_red.png);
}
.body-about {
background-image: url(../img/bg_blue.png);
}
.body-company {
background-image: url(../img/bg_green.png);
}
.body-contact {
background-image: url(../img/bg_yellow.png);
}
$setBG: (top red)(about blue)(company green)(contact yellow); $setBG: (top,red)(about,blue)(company,green)(contact,yellow); $setBG: ((top)(red))((about)(blue))((company)(green))((contact)(yellow));
シンプルなグラデーションのミックスインを作る
@mixin linear-gradient($color: #f00, $way:to bottom, $percent: 20%) {
background-image: linear-gradient($way,$color 0%, lighten($color, $percent) 100%);
}
.item {
@include linear-gradient;
}
.item {
background-image: linear-gradient(to bottom, #f00 0%, #ff6666 100%);
}
.item {
@include linear-gradient(#999, left, 50%);
}
.item {
background-image: linear-gradient(to bottom, #f00 0%, #ff6666 100%);
}
Map型と@eachを使ってSNSアイコンを管理する
// Map型を使って定義
$sns-colors: (
twitter: #1b95e0,
facebook: #3b5998,
googleplus: #dc4e41,
);
// SNSアイコン
.sns {
&__btn {
background-repeat: no-repeat;
// @each で処理を繰り返す
@each $key, $value in $sns-colors {
&.-#{$key} {
background-image: url(/img/icon_#{$name}.png);
background-color: $value;
}
}
}
}
.sns__btn {
background-repeat: no-repeat;
}
.sns__btn.-twitter {
background-image: url(/img/icon_twitter.png);
background-color: #1b95e0;
}
.sns__btn.-facebook {
background-image: url(/img/icon_facebook.png);
background-color: #3b5998;
}
.sns__btn.-googleplus {
background-image: url(/img/icon_googleplus.png);
background-color: #dc4e41;
}
// Mapを使ってファイル名と背景色を定義
$sns-colors: (
twitter: '01.png' '#1b95e0',
facebook: '02.jpg' '#3b5998',
googleplus: 'gplus.png' '#dc4e41',
);
// SNSアイコン
.sns {
&__btn {
background-repeat: no-repeat;
// @each で処理を繰り返す
@each $key, $values in $sns-colors {
&.-#{$key} {
background-image: url(/img/icon/#{nth($values, 1)});
background-color: #{nth($value, 2)};
}
}
}
}
.sns__btn {
background-repeat: no-repeat;
}
.sns__btn.-twitter {
background-image: url(/img/icon/01.png);
background-color: #1b95e0;
}
.sns__btn.-facebook {
background-image: url(/img/icon/02.jpg);
background-color: #3b5998;
}
.sns__btn.-googleplus {
background-image: url(/img/icon/gplus.png);
background-color: #dc4e41;
}
// SNS設定
$sns-config:(
colors: (
twitter: #1b95e0,
facebook: #3b5998,
googleplus: #dc4e41,
),
sizes: (
sm: 25%,
md: 50%,
lg: 100%,
)
);
// SNSアイコン
.sns {
&__btn {
@each $name, $color in map-get($sns-config, 'colors') {
&.-#{$name} {
background: $color url(/img/icon_#{$name}.png) no-repeat center;
}
}
@each $size, $width in map-get($sns-config, 'sizes') {
&.-#{$size} {
width: $width;
}
}
}
}
.sns__btn.-twitter {
background: #1b95e0 url(/img/icon_twitter.png) no-repeat center;
}
.sns__btn.-facebook {
background: #3b5998 url(/img/icon_facebook.png) no-repeat center;
}
.sns__btn.-googleplus {
background: #dc4e41 url(/img/icon_googleplus.png) no-repeat center;
}
.sns__btn.-sm {
width: 25%;
}
.sns__btn.-md {
width: 50%;
}
.sns__btn.-lg {
width: 100%;
}
値が比較しづらいz-indexをMap型で一括管理する
$layer: (
modal : 100,
header : 20,
tooltip : 10,
default : 1
);
@mixin z-index($key) {
z-index: map-get($layer, $key);
}
.modal {
@include z-index(modal);
}
.header {
@include z-index(header);
}
.tooltip {
@include z-index(tooltip);
}
.modal {
z-index: 100;
}
.header {
z-index: 20;
}
.tooltip {
z-index: 10;
}
@functionを使ってpx指定する感覚でフォントサイズをrem指定する
$baseFontSize: 16;
html {
font-size: $baseFontSize + px;
}
@function rem($pixels, $context: $baseFontSize) {
@return $pixels / $context * 1rem;
}
.text {
font-size: rem(12);
}
.text {
font-size: 0.875rem;
}
.text {
font-size: rem(14, 12);
}
.text {
font-size: 1.16667rem;
}
ネストしたセレクタをselector-replace()を使って書き換える
.block {
.item-A {
a {
background: red;
@at-root #{selector-replace(&,".item-A", ".item-B")} {
background: blue;
}
}
}
}
.block .item-A a {
background: red;
}
.block .item-B a {
background: blue;
}
@mixin replace($original, $replacement) {
@at-root {
#{selector-replace(&, $original, $replacement)} {
@content
}
}
}
.block {
.item {
a {
width: 85%;
@include replace(".block", ".block .inner") {
width: 100%;
}
}
}
}
.block .item a {
width: 85%;
}
.block .inner .item a {
width: 100%;
}
#main {
.block {
.link {
padding-left: 20px;
@include replace(".link", "a.link") {
display: inline-block;
padding-left: 15px;
}
}
}
}
#main .block .link {
padding-left: 20px;
}
#main .block a.link {
display: inline-block;
padding-left: 15px;
}
selector-extend() を使い、親セレクタだけ変更して同一スタイルを適用させる
.block {
.item-A {
padding: 10px;
ul {
width: 500px;
li {
margin-bottom: 10px;
a {
background: blue;
}
}
}
}
.item-B {
padding: 20px;
ul {
li {
a {
background: blue;
}
}
}
}
}
.block {
.item-A {
padding: 10px;
ul {
width: 500px;
li {
margin-bottom: 10px;
a {
@at-root #{selector-extend(&, ".item-A", ".item-B")} {
background: blue;
}
}
}
}
}
.item-B {
padding: 20px;
}
}
.block .item-A {
padding: 10px;
}
.block .item-A ul {
width: 500px;
}
.block .item-A ul li {
margin-bottom: 10px;
}
.block .item-A ul li a {
background: blue;
}
.block .item-B {
padding: 20px;
}
.block .item-B ul li a {
background: blue;
}
.block .item-A {
padding: 10px;
}
.block .item-A ul {
width: 500px;
}
.block .item-A ul li {
margin-bottom: 10px;
}
.block .item-A ul li a, .block
.item-B ul li a {
background: blue;
}
.block .item-B {
padding: 20px;
}

