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)) {
}
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)) {
}
Câu trả lời:
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ácvar()
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-breakpoint
ví 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ế.
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-drafts
GitHub # 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 # 1693 và nhậ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
@media
cá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 # 2627 và GitHub # 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.
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.
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.
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;
}
}
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) {}
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:
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 = '..'
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ị 1px
với các giá trị của biến css --replace-media-1px
, quy tắc có giá trị 2px
với --replace-media-2px
và 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-height
và max-height
ngay 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) {
...
}