Biến gốc CSS không hoạt động trong truy vấn phương tiện


140

Tôi đang cố gắng sử dụng các biến CSS trong truy vấn phương tiện và nó không hoạt động.

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

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

}

Bạn đã thử trong một số trình duyệt? (Giống như Chrome và Firefox)
Cohars

1
Không có tiền xử lý @SandrinaPereira
Cohars

1
@SandrinaPereira Vì vậy, bạn có thể trên Firefox và Chrome
Cohars


3
Chỉ cần làm rõ cho những người tìm thấy điều này thông qua Google: bạn có thể sử dụng các thuộc tính tùy chỉnh CSS bên trong phạm vi của truy vấn phương tiện, bạn không thể sử dụng chúng trong khai báo truy vấn phương tiện.
David Deprost

Câu trả lời:


112

Từ thông số kỹ thuật ,

Các var()chức năng có thể được sử dụng ở vị trí của bất kỳ phần nào của một giá trị trong bất kỳ tài sản trên một phần tử. Các var()chức năng không thể được sử dụng như tên thuộc tính, chọn lọc, hoặc bất cứ điều gì khác ngoài giá trị tài sản. (Làm như vậy thường tạo ra cú pháp không hợp lệ hoặc nếu không thì giá trị có nghĩa không có kết nối với biến.)

Vì vậy, không, bạn không thể sử dụng nó trong một truy vấn phương tiện truyền thông.

Và điều đó có ý nghĩa. Bởi vì bạn có thể đặt --mobile-breakpointví dụ để :root, có nghĩa là, các <html>yếu tố, và từ đó được thừa hưởng đến các yếu tố khác. Nhưng truy vấn phương tiện không phải là một yếu tố, nó không được kế thừa từ đó <html>, vì vậy nó không thể hoạt động.

Đây không phải là những gì các biến CSS đang cố gắng thực hiện. Bạn có thể sử dụng bộ tiền xử lý CSS thay thế.


77
Câu trả lời là chính xác ở chỗ thông số kỹ thuật hiện không xử lý các biến CSS trong các truy vấn phương tiện, nhưng không chính xác đó không phải là biến CSS đang cố gắng thực hiện. Giảm số lần lặp lại và số ma thuật chính xác là lý do tại sao các biến CSS được tạo - xem w3.org/TR/css-variables-1/#intro
mikemaccana

69

Như Oriol đã trả lời , hiện tại, các biến CSS cấp 1 var()không thể được sử dụng trong các truy vấn phương tiện . Tuy nhiên, đã có những phát triển gần đây sẽ giải quyết vấn đề này. Trong một vài năm, khi Mô-đun Biến đổi Môi trường CSS Cấp 1 được chuẩn hóa và triển khai, chúng tôi sẽ có thể sử dụng env()các biến trong truy vấn phương tiện trong tất cả các trình duyệt hiện đại.

Nếu bạn đọc đặc tả và có một mối quan tâm, hoặc nếu bạn muốn nói lên sự hỗ trợ của mình cho trường hợp sử dụng truy vấn phương tiện, bạn vẫn có thể làm như vậy trong GitHub w3c / csswg-dự thảo # 1693 hoặc trong bất kỳ vấn đề GitHub CSS nào có tiền tố với [ css-env-1]” .


Câu trả lời gốc 2017-11-09 : Gần đây, Nhóm làm việc CSS đã quyết định rằng Biến CSS cấp 2 sẽ hỗ trợ các biến môi trường do người dùng xác định bằng cách sử dụng env()và họ sẽ cố gắng làm cho chúng hợp lệ trong các truy vấn phương tiện . Tập đoàn đã giải quyết vấn đề này sau khi Apple đề xuất các thuộc tính tác nhân người dùng tiêu chuẩn đầu tiên , ngay trước khi có thông báo chính thức về iPhone X vào tháng 9 năm 2017 (xem thêm WebKit: Trang thiết kế trang web cho iPhone X. của Timothy Horton ). Các đại diện trình duyệt khác sau đó đồng ý rằng chúng thường hữu ích trên nhiều thiết bị, chẳng hạn như màn hình tivi và in mực với các cạnh bị chảy máu. ( env()được gọi làconstant(), nhưng điều đó đã bị phản đối. Bạn vẫn có thể thấy các bài viết đề cập đến tên cũ, chẳng hạn như bài viết này của Peter-Paul Koch .) Sau một vài tuần trôi qua, Cameron McCormack của Mozilla nhận ra rằng các biến môi trường này sẽ có thể sử dụng được trong các truy vấn truyền thông và Tab Atkins, Jr. của Google sau đó nhận ra rằng các biến môi trường do người dùng xác định sẽ đặc biệt hữu ích như các biến gốc không thể ghi đè toàn cục, có thể sử dụng được trong các truy vấn phương tiện. Bây giờ, Trưởng khoa Dino Dino Jackson của Apple sẽ cùng Atkins chỉnh sửa Cấp độ 2.

Bạn có thể đăng ký để cập nhật về vấn đề này trong số w3c/csswg-draftsGitHub # 1693 . (Để biết chi tiết lịch sử đặc biệt có liên quan, hãy mở rộng nhật ký cuộc họp được nhúng trong độ phân giải của Cuộc họp Bot của CSSWG và tìm kiếm cho MQiên , viết tắt của truy vấn phương tiện truyền thông.

Tôi dự định cập nhật câu hỏi này trong tương lai khi có nhiều phát triển xảy ra. Tương lai thật thú vị.


Cập nhật 2018-02-08 : Safari Technology Preview 49 đã thêm hỗ trợ để phân tích cú pháp calc()trong các truy vấn phương tiện, đây có thể là khúc dạo đầu để hỗ trợ env()chúng.


Cập nhật 2018-04-27 : Nhóm Chromium tại Google đã quyết định bắt đầu làm việc env(). Đáp lại, Atkins đã bắt đầu chỉ định env()trong một tiêu chuẩn dự thảo riêng, không chính thức: Mô-đun Biến đổi Môi trường CSS Cấp 1 . (Xem bình luận GitHub của anh ấy trong w3c / csswg-dự thảo # 1693nhận xét của anh ấy trong w3c / csswg-dự thảo # 1817. ) Dự thảo gọi ra các biến trong truy vấn phương tiện như một trường hợp sử dụng rõ ràng:

Vì các biến môi trường không phụ thuộc vào giá trị của bất kỳ thứ gì được rút ra từ một phần tử cụ thể, nên chúng có thể được sử dụng ở những nơi không có phần tử rõ ràng để rút ra, chẳng hạn như trong @mediacác quy tắc, trong đó var()hàm sẽ không hợp lệ.

Nếu bạn đọc đặc tả và có một mối quan tâm, hoặc nếu bạn muốn nói lên sự hỗ trợ của mình cho trường hợp sử dụng truy vấn phương tiện, bạn vẫn có thể làm như vậy trong GitHub w3c / csswg-dự thảo # 1693 hoặc trong bất kỳ vấn đề GitHub CSS nào có tiền tố với [ css-env-1]” .


Cập nhật 2019-07-06 : Công việc tiếp tục về thông số kỹ thuật. Vấn đề GitHub # 2627GitHub # 3578 được dành cho các biến môi trường tùy chỉnh trong các truy vấn phương tiện.


31

Tuy nhiên, những gì bạn CÓ THỂ làm là @media truy vấn câu lệnh gốc của bạn!

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

Hoàn toàn hoạt động trong Chrome, Firefox và Edge ít nhất là các phiên bản sản xuất mới nhất kể từ khi đăng bài này.


Ồ cảm ơn nhé! Điều này chắc chắn nên là câu trả lời chính xác.
SimplyComplexable

1
Tốt để biết. Một hạn chế: Nếu cũng cần truy cập giá trị đó dưới dạng a var, do đó có thể sử dụng trong các phép tính ở nơi khác css, điều này vẫn yêu cầu đặt "giá trị ma thuật" (ở đây, 479px) ở hai vị trí: truy vấn phương tiện và khai báo var.
ToolmakerSteve

8

Rõ ràng là không thể sử dụng các biến CSS nguyên gốc như thế. Đó là một trong những hạn chế .

Một cách thông minh để sử dụng nó là thay đổi các biến của bạn trong truy vấn phương tiện, để tác động đến tất cả phong cách của bạn. Tôi đề nghị bài viết này .

:root {
  --gutter: 4px;
}

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

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

Tôi không hiểu ý nghĩa của "thay đổi biến của bạn trong truy vấn phương tiện", bạn có thể hiển thị ví dụ?

1
Đây không phải là ý tôi. Tôi hỏi về giá trị truy vấn phương tiện truyền thông.

4
Vâng, vừa mới làm, đó là trong bài viết tôi liên kết. Tôi biết đó không phải là những gì bạn mong đợi, nhưng các biến CSS không thể được sử dụng để xác định các truy vấn phương tiện
Cohars

8

Một cách để đạt được những gì bạn muốn là sử dụng gói npm postcss-media-variables.

Nếu bạn ổn với việc sử dụng các gói npm thì bạn có thể xem tài liệu cho cùng ở đây

Thí dụ

/* 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) {}

4
Cảm ơn, nhưng tôi đã cố gắng không sử dụng bất kỳ bộ tiền xử lý nào.

et. al: Với postcss, bạn cũng có thể sử dụng cssnext cssnext.io/features/#custom-media-queries
sebilasse

1
@sebilasse: truy vấn phương tiện truyền thông tùy chỉnh không giải quyết vấn đề chính là không thể sử dụng biến css làm điểm dừng cho truy vấn phương tiện
zhirzh

1
postcss không phải là bộ tiền xử lý

1

Như bạn có thể đọc các câu trả lời khác, vẫn không thể làm như vậy.

Ai đó đã đề cập đến các biến môi trường tùy chỉnh (tương tự như biến css tùy chỉnh env()thay vì var()) và nguyên tắc là âm thanh, mặc dù vẫn còn 2 vấn đề chính:

  • hỗ trợ trình duyệt yếu
  • cho đến nay không có cách nào để định nghĩa chúng (nhưng có lẽ sẽ có trong tương lai, vì đây chỉ là một dự thảo không chính thức)

1

Câu trả lời ngắn

Bạn có thể sử dụng JavaScript để thay đổi giá trị của các truy vấn phương tiện và đặt nó thành giá trị của biến 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 = '..'


Câu trả lời dài

Tôi đã viết một kịch bản nhỏ mà bạn có thể đưa vào trang của mình. Nó thay thế tất cả các quy tắc phương tiện truyền thông với một giá trị 1pxvới các giá trị của biến css --replace-media-1px, quy tắc có giá trị 2pxvới --replace-media-2pxvà vân vân. Này làm việc cho các truy vấn phương tiện truyền thông with, min-width, max-width, height, min-heightmax-heightngay cả khi chúng được kết nối sử dụng and.

JavaScript:

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) {
  ...
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.