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
          ...

이것은 실제로 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

6
SASS가 @media 쿼리 내에서 $ 변수와 함께 작동하지 않는 경우가 여전히 있습니까?
HappyTorso

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

1
yep sass는 전 처리기입니다. "이것은 단순히 가능하지 않습니다"라는 이유가 없습니다. 할 수 있고 구현되지 않았습니다.
Ini 2011

54

Philipp Zedler의 답변과 유사하게 mixin으로 할 수 있습니다. 원하는 경우 단일 파일에 모든 것을 포함 할 수 있습니다.

    @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/cross-media-query-extend-sass
InsOp

이것은 내 대답보다 낫습니다!
Philipp Zedler

+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가 생성됩니다. 반복적 인 미디어 쿼리는 파일 크기를 증가 시키지만, 웹 서버가 적용 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의 답변과 동일한 기술입니다. 내가 그 연결했다 때까지 어떤 방법으로 그것의 가치를 할인 아니지만, 그것은 이해하기 어렵습니다
존 노이 하우스를

5

나는 같은 문제가 있었다.

$menu-width변수는에 240 픽셀이어야합니다 모바일@media only screen and (max-width : 768px)온 및 340px 바탕 화면 보기.

그래서 간단히 두 개의 변수를 만들었습니다.

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

그리고 내가 그것을 사용한 방법은 다음과 같습니다.

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

1

두 가지 권장 사항

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

이 개 경우 사용 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.