[css] 미디어 쿼리에서 작동하지 않는 CSS 기본 변수

미디어 쿼리에서 CSS 변수를 사용하려고하는데 작동하지 않습니다.

:root {
  --mobile-breakpoint: 642px;
}

@media (max-width: var(--mobile-breakpoint)) {

}



답변

로부터 사양 ,

var()함수는 요소의 속성에서 값의 일부를 대신하여 사용할 수 있습니다. 그만큼var() 기능은 속성 이름, 선택기 또는 속성 값 이외의 다른 것으로 사용할 수 없습니다. (이렇게하면 일반적으로 유효하지 않은 구문 또는 그 의미가 변수와 연결되지 않은 값을 생성합니다.)

따라서 미디어 쿼리에서는 사용할 수 없습니다.

그리고 그것은 말이됩니다. 사용자가 설정할 수 있기 때문에 --mobile-breakpoint예를 들어합니다 :root,이다의 <html>요소, 그리고 거기에서 다른 요소에 상속. 그러나 미디어 쿼리는 요소가 아니며에서 상속받지 <html>않으므로 작동 할 수 없습니다.

이것은 CSS 변수가 달성하려는 것이 아닙니다. 대신 CSS 프리 프로세서를 사용할 수 있습니다.


답변

Oriol이 대답 했듯이 현재 CSS 변수 레벨 1 var()은 미디어 쿼리에 사용할 수 없습니다 . 그러나이 문제를 해결하기위한 최근의 개발이있었습니다. 몇 년 후 CSS 환경 변수 모듈 수준 1 이 표준화되고 구현되면 env()모든 최신 브라우저에서 미디어 쿼리에 변수 를 사용할 수 있습니다 .

사양 을 읽고 우려 사항이 있거나 미디어 쿼리 사용 사례에 대한 지원을 표명하려는 경우 여전히 GitHub w3c / csswg-drafts # 1693 또는 접두사 “[ css-env-1]” .


원래 대답 2017년 11월 9일 : 최근에, CSS 워킹 그룹은 결정 하는 것이 CSS 변수 레벨 2를 사용하여 사용자 정의 환경 변수를 지원합니다 env(), 그들은 그들이 미디어 쿼리에 유효하게하려고합니다 . 그룹 은 Apple 이 2017 년 9 월 iPhone X의 공식 발표 직전에 표준 사용자 에이전트 속성을 처음 제안한 후에 이를 해결했습니다 ( WebKit : Timothy Horton의“iPhone X 용 웹 사이트 디자인” 참조 ). 그런 다음 다른 브라우저 담당자는 일반적으로 텔레비전 디스플레이 및 블리드 가장자리가있는 잉크 인쇄와 같은 많은 장치에서 유용 할 것이라고 동의했습니다. (이전 env()에는constant()하지만 이제는 더 이상 사용되지 않습니다. Peter-Paul Koch의이 기사 와 같이 이전 이름을 가리키는 기사가 계속 표시 될 수 있습니다 . 몇 주가 지난 후 Mozilla의 Cameron McCormack은 있음 깨달았습니다. 와 레벨 2 편집에 입니다.이러한 환경 변수는 미디어 쿼리에서 사용할 수 있으며 Google의 Tab Atkins Jr.는 사용자 정의 환경 변수가 미디어 쿼리에서 사용할 수있는 재정의 할 수없는 전역 루트 변수로 특히 유용 하다는 것을 깨달았습니다 . 이제 Apple의 Dean “Dino”Jackson이 Atkins에 합류합니다

GitHub 문제 # 1693 에서이 문제에 대한 업데이트를 구독 할 수 있습니다.w3c/csswg-drafts . (특히 관련 기록 세부 정보를 보려면 CSSWG Meeting Bot의 해상도에 포함 된 회의 로그를 확장하십시오. “미디어 쿼리”를 나타내는 “MQ”를 검색하십시오.)

앞으로 더 많은 개발이 진행될 때이 질문을 업데이트 할 계획입니다. 미래는 흥미 롭습니다.


2018 년 2 월 8 일 업데이트 :
Safari Technology Preview 49calc()미디어 쿼리의 구문 분석 기능을 추가로 지원 env()합니다.


2018-04-27 업데이트 : Google의 Chromium 팀에서 작업을 시작하기로 결정했습니다 env(). 이에 따라 Atkins는 env()별도의 비공식 초안 표준 인 CSS 환경 변수 모듈 레벨 1 을 지정하기 시작했습니다 . ( w3c / csswg-drafts # 1693의 GitHub 주석w3c / csswg-drafts # 1817의 주석을 참조하십시오 . 초안은 미디어 쿼리에서 변수를 명시 적 사용 사례로 호출합니다.

환경 변수는 특정 요소에서 가져온 것의 값에 의존하지 않기 때문에 함수 와 같이 유효하지 않은 @media규칙 과 같이 명확한 요소가없는 곳에서 사용할 수 있습니다 var().

사양을 읽고 우려 사항이 있거나 미디어 쿼리 사용 사례에 대한 지원을 표명하려는 경우 여전히 GitHub w3c / csswg-drafts # 1693 또는 접두사 “[ css-env-1]” .


2019-07-06 업데이트 : 사양에 대한 작업이 계속됩니다. GitHub 문제 # 2627GitHub 문제 # 3578 은 미디어 쿼리의 사용자 지정 환경 변수에 전념합니다.


답변

그러나 당신이 할 수있는 일은 @media query : : root statement입니다!

:root {
     /* desktop vars */
}
@media screen and (max-width: 479px) {
    :root {
        /* mobile vars */
    }
}

이 게시물 기준으로 최소한 최신 프로덕션 버전 인 Chrome, Firefox 및 Edge에서 완전히 작동합니다.


답변

분명히 네이티브 CSS 변수를 사용하는 것은 불가능합니다. 그것은 한계 중 하나입니다 .

그것을 사용하는 영리한 방법은 미디어 쿼리에서 변수를 변경하여 모든 스타일에 영향을 미치는 것입니다. 이 기사를 추천 합니다 .

:root {
  --gutter: 4px;
}

section {
  margin: var(--gutter);
}

@media (min-width: 600px) {
  :root {
    --gutter: 16px;
  }
}


답변

원하는 것을 달성하는 한 가지 방법은 npm 패키지를 사용하는 것입니다. postcss-media-variables 입니다.

npm 패키지를 사용하는 것이 좋으면 여기에서 동일한 문서를 볼 수 있습니다

/* input */
:root {
  --min-width: 1000px;
  --smallscreen: 480px;
}
@media (min-width: var(--min-width)) {}
@media (max-width: calc(var(--min-width) - 1px)) {}

@custom-media --small-device (max-width: var(--smallscreen));
@media (--small-device) {}


답변

다른 답변을 읽을 수 있지만 여전히 불가능합니다 수는 .

누군가가 사용자 정의 환경 변수를 언급하고 ( env()대신에 사용자 정의 CSS 변수와 유사 var()) 원칙은 건전하지만 여전히 두 가지 주요 문제가 있습니다.

  • 약한 브라우저 지원
  • 지금까지 그것들을 정의 할 수있는 방법은 없습니다 (그러나 이것은 비공식 초안 일 뿐이므로 앞으로있을 것입니다)

답변

짧은 답변

JavaScript를 사용하여 미디어 쿼리 값을 변경하고이를 CSS 변수 값으로 설정할 수 있습니다.

// get value of css variable
getComputedStyle(document.documentElement).getPropertyValue('--mobile-breakpoint'); // '642px'

// search for media rule
var mediaRule = document.styleSheets[i].cssRules[j];

// update media rule
mediaRule.media.mediaText = '..'

긴 답변

귀하의 페이지에 포함시킬 수있는 작은 스크립트를 작성했습니다. 그것은의 값으로 모든 미디어 규칙을 대체 1px하는 CSS 변수의 값으로 --replace-media-1px, 값 규칙 2px--replace-media-2px등등합니다. 이것은 미디어 쿼리 작동 with, min-width, max-width, height, min-height그리고 max-height그들이 사용하여 연결하는 경우에도 and.

자바 스크립트 :

function* visitCssRule(cssRule) {
    // visit imported stylesheet
    if (cssRule.type == cssRule.IMPORT_RULE)
        yield* visitStyleSheet(cssRule.styleSheet);

    // yield media rule
    if (cssRule.type == cssRule.MEDIA_RULE)
        yield cssRule;
}

function* visitStyleSheet(styleSheet) {
    try {
        // visit every rule in the stylesheet
        var cssRules = styleSheet.cssRules;
        for (var i = 0, cssRule; cssRule = cssRules[i]; i++)
            yield* visitCssRule(cssRule);
    } catch (ignored) {}
}

function* findAllMediaRules() {
    // visit all stylesheets
    var styleSheets = document.styleSheets;
    for (var i = 0, styleSheet; styleSheet = styleSheets[i]; i++)
        yield* visitStyleSheet(styleSheet);
}

// collect all media rules
const mediaRules = Array.from(findAllMediaRules());

// read replacement values
var style = getComputedStyle(document.documentElement);
var replacements = [];
for (var k = 1, value; value = style.getPropertyValue('--replace-media-' + k + 'px'); k++)
    replacements.push(value);

// update media rules
for (var i = 0, mediaRule; mediaRule = mediaRules[i]; i++) {
    for (var k = 0; k < replacements.length; k++) {
        var regex = RegExp('\\((width|min-width|max-width|height|min-height|max-height): ' + (k+1) + 'px\\)', 'g');
        var replacement = '($1: ' + replacements[k] + ')';
        mediaRule.media.mediaText = mediaRule.media.mediaText.replace(regex, replacement);
    }
}

CSS :

:root {
  --mobile-breakpoint: 642px;

  --replace-media-1px: var(--mobile-breakpoint);
  --replace-media-2px: ...;
}

@media (max-width: 1px) { /* replaced by 642px */
  ...
}

@media (max-width: 2px) {
  ...
}