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


120

次のように、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;と、未定義の変数に対してエラーが返されることにも注意してください。私が見逃しているアイデアはありますか?


回答:


96

これは不可能です。トリガー@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
          ...

これは本当にドライではありませんが、あなたができる最高のことです。

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

@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

6
SASSが@mediaクエリ内の$ variablesで機能しない場合はまだありますか?
HappyTorso 2014

1
@HappyTorsoクライアント側のSassコンパイラー(JavaScriptなど)などがビューポートのサイズ変更で実行されるまで、常にそうなります。Sass変数はビルド時に静的な値にコンパイルされます。実行時には存在しません。メディアクエリは、クエリのメディア属性が変更されると、実行時に評価されます。
ericsoco

26
@ericsocoそれが理由である理由がわかりません。SASSは簡単に(?)変数のすべての使用状況を追跡し、それらが使用されている場所にメディアクエリを挿入できます。$foo: 1rem; @media (min-width: 10rem) {$foo: 2rem} .class {font-size: $foo} .class2 {padding: $foo}結果は.class {font-size: 1rem} .class2 {padding: 1rem} @media (min-width: 10rem) (.class {font-size: 2rem} .class2 {padding: 2rem}}
powerbuoy 2016

1
yep sassはプリプロセッサです。「これは単に不可能です」という理由はありません...それは可能ですが、実装されていません。
Ini

54

フィリップゼドラーの答えと同様に、ミックスインを使用してそれを行うことができます。これにより、必要に応じてすべてを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);
    }

1
遅かれ早かれ、この問題に遭遇するでしょう。sitepoint.com
media

これは私の答えよりも優れています!
Philipp Zedler、2017年

+1はこのソリューションが大好きです。これをマップ(sass-lang.com/documentation/functions/map)と組み合わせると、ある程度の力が得られます。ここでは、説明するために別のソリューションを作成します。編集:完了。stackoverflow.com/a/56894640/385273
Ben

9

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

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ステートメントだけです。


9

これは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;
  }
}

8

@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
        ));
    }

.myDivさまざまな値の束をターゲットにしたDRYメディアクエリをさらに多く設定できるようになりました。


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

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


表示に1秒かかりましたが、これは@ronenの回答と同じテクニックで、マップ入力を使用して一度に複数の変数をサポートします。私はそれの価値を決して値下げしていませんが、その関係を作るまで理解するのは困難でした
John Neuhaus '22

5

私も同じ問題を抱えていました。

$menu-width変数は、上で240ピクセルでなければなりませんモバイルビュー@media only screen and (max-width : 768px)上と340px のデスクトップビュー。

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

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

そしてここに私がそれをどのように使用したかがあります:

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

1

2つの推奨事項

1 小さな画面用に「デフォルト」のCSSステートメントを記述し、大きな画面にのみメディアクエリを使用します。通常、max-widthメディアクエリは必要ありません。

例(要素にクラス「container」があると想定)

@mixin min-width($width) {
  @media screen and (max-width: $width) {
    @content;
  }
}

.container {
  width: 960px;

  @include min-width(1170px) {
    width: 1160px;
  }
}

2 可能な場合は、CSS変数を使用して問題を解決します

@mixin min-width($width) {
  @media screen and (max-width: $width) {
    @content;
  }
}

:root {
  --container-width: 960px;
  @include min-width(1170px) {
    --container-width: 1160px;
  }
}

.container {
  width: var(--container-width);
}

注意:

ウィンドウの幅が1170pxの場合は1160pxの幅になるため、100%の幅と1160pxの最大幅を使用することをお勧めします。また、親要素は5pxの水平方向のパディングを持つことができます。 box-sizingプロパティはborder-boxに設定されています。問題を解決する方法はたくさんあります。親がフレックスまたはグリッドコンテナーでない場合は、を使用できます.container { margin: auto }

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.