web-dev-qa-db-ja.com

CSS3メディアクエリでのSass変数の使用

次のように、Sass変数の使用と@mediaクエリを組み合わせようとしています。

$base_width:1160px;

@media screen and (max-width: 1170px) {$base_width: 960px;}
@media screen and (min-width: 1171px) {$base_width: 1160px;}

$base_widthは、スタイルシートの幅のパーセンテージに基づく測定のさまざまなポイントで定義され、流動的なレイアウトを生成します。

これを行うと、変数は適切に認識されるように見えますが、メディアクエリの条件は認識されません。たとえば、上記のコードは画面の幅に関係なく1160pxのレイアウトを生成します。 @mediaステートメントを次のようにフリップフロップすると:

@media screen and (min-width: 1171px) {$base_width: 1160px;}
@media screen and (max-width: 1170px) {$base_width: 960px;}

これも画面幅に関係なく、960pxのレイアウトを生成します。また、$base_width: 1160px;の最初の行を削除すると、未定義の変数に対してエラーが返されることに注意してください。私が欠けているものはありますか?

87
Jeremy S.

これは単に不可能です。トリガー@media screen and (max-width: 1170px)はクライアント側で発生するため。

SASSが$base_width変数を含むスタイルシートのすべてのルールとプロパティを取得し、それに応じてコピー/変更した場合にのみ、期待した結果を達成できます。

自動的に動作しないため、次のように手動で実行できます。

@media screen and (max-width: 1170px)
      $base_width: 960px // you need to indent it to (re)set it just within this media-query
      // now you copy all the css rules/properties that contain or are relative to $base_width e.g.
      #wrapper
          width: $base_width
          ...

@media screen and (min-width: 1171px)
    $base_width: 1160px
      #wrapper
          width: $base_width
          ...

これは実際にはDRYではありませんが、最善の方法です。

変更が毎回同じである場合、すべての変更値を含むミックスインを準備することもできるので、繰り返す必要はありません。さらに、ミックスインと特定の変更を組み合わせることもできます。好む:

@media screen and (min-width: 1171px)
    +base_width_changes(1160px)
    #width-1171-specific-element // additional specific changes, that aren't in the mixin
        display: block

Mixinは次のようになります

=base_width_changes($base_width)
    #wrapper
        width: $base_width
80
woerndl

Philipp Zedlerの答えと同様に、mixinでそれを行うことができます。これにより、必要に応じてすべてを1つのファイルに収めることができます。

@mixin styling($base-width) {
    // your SCSS here, e.g.
    #Contents {
        width: $base-width;
    }
}

@media screen and (max-width: 1170px) {
    @include styling($base-width: 960px);
}
@media screen and (min-width: 1171px) {
    @include styling($base-width: 1160px);
}
39
ronen

編集:このソリューションは使用しないでください。 ronenの答えははるかに優れています。

DRYソリューションとして、@importメディアクエリ内のステートメント。このような。

@media screen and (max-width: 1170px) {
    $base_width: 960px;
    @import "responsive_elements";
}
@media screen and (min-width: 1171px) {
    $base_width: 1160px;
    @import "responsive_elements";
}

メディアクエリで定義された変数を使用して、含まれるファイルのすべてのレスポンシブ要素を定義します。したがって、繰り返す必要があるのはimportステートメントだけです。

6
Philipp Zedler

同じ問題がありました。

$menu-width変数は、mobileビュー@media only screen and (max-width : 768px)で240px、desktopビューで340pxである必要があります。

だから私は単に2つの変数を作成しました:

$menu-width: 340px;
$menu-mobile-width: 240px;

そして、ここに私がそれを使用した方法があります:

.menu {
    width: $menu-width;
    @media only screen and (max-width : 768px) {
      width: $menu-mobile-width;
    }
}
2
Dawid Dyrcz

これはSASSでは不可能ですが、CSS変数(または CSSカスタムプロパティ )では可能です。唯一の欠点はブラウザのサポートです。しかし、実際にはPostCSSプラグインがあります- postcss-css-variables -CSS変数の使用を「フラット化」します(古いブラウザもサポートします)。

次の例は、SASSでうまく機能します(また、postcss-css-variablesを使用すると、古いブラウザーもサポートされます)。

$mq-laptop: 1440px;
$mq-desktop: 1680px;

:root {
    --font-size-regular: 14px;
    --Gutter: 1rem;
}

// The fact that we have to use a `max-width` media query here, so as to not
// overlap with the next media query, is a quirk of postcss-css-variables
@media (min-width: $mq-laptop) and (max-width: $mq-desktop - 1px) {
    :root {
        --font-size-regular: 16px;
        --Gutter: 1.5rem;
    }
}

@media (min-width: $mq-desktop) {
    :root {
        --font-size-regular: 18px;
        --Gutter: 1.75rem;
    }
}

.my-element {
    font-size: var(--font-size-regular);
    padding: 0 calc(var(--Gutter) / 2);
}

これにより、次のCSSが生成されます。繰り返しメディアクエリを実行するとファイルサイズが増加しますが、Webサーバーがgzip(通常は自動的に適用します)を適用すると、その増加は通常無視できることがわかりました。

.my-element {
  font-size: 14px;
  padding: 0 calc(1rem / 2);
}
@media (min-width: 1680px) {
  .my-element {
  padding: 0 calc(1.75rem / 2);
  }
}
@media (min-width: 1440px) and (max-width: 1679px) {
  .my-element {
  padding: 0 calc(1.5rem / 2);
  }
}
@media (min-width: 1680px) {
  .my-element {
  font-size: 18px;
  }
}
@media (min-width: 1440px) and (max-width: 1679px) {
  .my-element {
  font-size: 16px;
  }
}
2
fredrikekelund

@ronenの 偉大な答え とマップを使用すると、実際のパワーを利用できます。

@mixin styling($map) {
    .myDiv {
        background: map-get($map, 'foo');
        font-size: map-get($map, 'bar');
    }
}

@media (min-height: 500px) {
    @include styling((
        foo: green,
        bar: 50px
    ));
}

@media (min-height: 1000px) {
    @include styling((
        foo: red,
        bar: 100px
    ));
}

さらに多くのDRYメディアクエリターゲティング.myDivさまざまな値の束。


マップドキュメント: https://sass-lang.com/documentation/functions/map

マップの使用例: https://www.sitepoint.com/using-sass-maps/

1
Ben