Variabel asli CSS tidak berfungsi di kueri media

140

Saya mencoba menggunakan variabel CSS dalam kueri media dan tidak berfungsi.

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

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

}

sumber
Sudahkah Anda mencoba di beberapa browser? (Seperti Chrome dan Firefox)
Cohars
1
Tanpa preprocessor @SandrinaPereira
Cohars
1
@SandrinaPereira Jadi Anda dapat menggunakan Firefox dan Chrome πŸ‘
Cohars
3
Hanya untuk mengklarifikasi bagi orang yang menemukan ini melalui Google: Anda dapat menggunakan properti khusus CSS di dalam lingkup kueri media, Anda tidak dapat menggunakannya dalam deklarasi kueri media.
David Deprost

Jawaban:

112

Dari spec ,

The var()fungsi dapat digunakan di tempat setiap bagian dari nilai properti apapun pada elemen. The var()Fungsi tidak dapat digunakan sebagai nama properti, penyeleksi, atau apa pun selain nilai properti. (Melakukannya biasanya menghasilkan sintaks yang tidak valid, atau nilai yang maknanya tidak memiliki koneksi ke variabel.)

Jadi tidak, Anda tidak dapat menggunakannya dalam kueri media.

Dan itu masuk akal. Karena Anda dapat mengatur --mobile-breakpointmisalnya untuk :root, yaitu <html>elemen, dan dari sana diwariskan ke elemen lain. Tapi kueri media bukan elemen, tidak diwarisi dari <html>, jadi tidak bisa.

Ini bukan yang ingin dicapai oleh variabel CSS. Anda dapat menggunakan preprocessor CSS sebagai gantinya.

Oriol
sumber
77
Jawabannya benar karena spec saat ini tidak menangani variabel CSS dalam kueri media, tetapi salah dalam hal itu yang bukan variabel CSS yang ingin dicapai. Mengurangi pengulangan dan sihir nomor adalah persis mengapa variabel CSS diciptakan - lihat w3.org/TR/css-variables-1/#intro
mikemaccana
69

Saat Oriol menjawab , saat ini, Variabel CSS Level 1 var()tidak dapat digunakan dalam kueri media . Namun, ada perkembangan terbaru yang akan mengatasi masalah ini. Dalam beberapa tahun, setelah Modul Lingkungan Variabel CSS Level 1 distandarisasi dan diimplementasikan, kami akan dapat menggunakan env()variabel dalam kueri media di semua browser modern.

Jika Anda membaca spesifikasi dan memiliki kekhawatiran, atau jika Anda ingin menyuarakan dukungan Anda untuk kasus penggunaan kueri media, Anda masih dapat melakukannya di GitHub w3c / csswg-draft # 1693 atau dalam masalah CSS GitHub apa pun yang diawali dengan β€œ[ css-env-1] " .


Jawaban asli 2017-11-09 : Baru-baru ini, Kelompok Kerja CSS memutuskan bahwa Variabel CSS Level 2 akan mendukung variabel lingkungan yang ditentukan pengguna menggunakan env(), dan mereka akan mencoba membuatnya valid dalam permintaan media . Grup menyelesaikan ini setelah Apple pertama kali mengusulkan properti agen-pengguna standar , tak lama sebelum pengumuman resmi iPhone X pada September 2017 (lihat juga WebKit: "Merancang Situs Web untuk iPhone X" oleh Timothy Horton ). Perwakilan browser lain kemudian sepakat bahwa mereka umumnya akan berguna di banyak perangkat, seperti tampilan televisi dan pencetakan tinta dengan tepi yang berdarah. ( env()Dahulu disebutconstant(), tapi itu sekarang sudah usang. Anda mungkin masih melihat artikel yang merujuk pada nama lama, seperti artikel ini oleh Peter-Paul Koch .) Setelah beberapa minggu berlalu, Cameron McCormack dari Mozilla menyadari bahwa variabel lingkungan ini akan dapat digunakan dalam permintaan media, dan Tab Atkins, Jr. Google kemudian menyadari bahwa variabel lingkungan yang ditentukan pengguna akan sangat berguna sebagai variabel root global, yang tidak dapat ditimpa, yang dapat digunakan dalam permintaan media. Sekarang, Dean β€œDino” Jackson dari Apple akan bergabung dengan Atkins dalam menyunting Level 2.

Anda dapat berlangganan pembaruan tentang masalah ini dalam w3c/csswg-draftsmasalah GitHub # 1693 . (Untuk detail historis yang relevan, perluas log pertemuan yang tertanam dalam resolusi Bot Rapat CSSWG dan cari "MQ", yang merupakan singkatan dari "kueri media".)

Saya berencana untuk memperbarui pertanyaan ini di masa mendatang ketika lebih banyak perkembangan terjadi. Masa depan itu menyenangkan.


Pembaruan 2018-02-08 : Safari Technology Preview 49 telah menambahkan dukungan untuk penguraian calc()dalam kueri media, yang mungkin merupakan awal untuk mendukungnya env()juga.


Pembaruan 2018-04-27 : Tim Chromium di Google telah memutuskan untuk mulai bekerja env(). Sebagai tanggapan, Atkins telah mulai menentukan env()secara terpisah, rancangan standar tidak resmi: Modul Variabel Lingkungan CSS Level 1 . (Lihat komentar GitHub di w3c / csswg-draft # 1693 dan komentarnya di w3c / csswg-draft # 1817. ) Konsep tersebut memanggil variabel dalam kueri media sebagai kasus penggunaan eksplisit:

Karena variabel lingkungan tidak bergantung pada nilai apa pun yang diambil dari elemen tertentu, mereka dapat digunakan di tempat-tempat di mana tidak ada elemen yang jelas untuk diambil, seperti dalam @mediaaturan, di mana var()fungsi tidak akan valid.

Jika Anda membaca spesifikasi dan memiliki kekhawatiran, atau jika Anda ingin menyuarakan dukungan Anda untuk kasus penggunaan kueri media, Anda masih dapat melakukannya di GitHub w3c / csswg-draft # 1693 atau dalam masalah CSS GitHub apa pun yang diawali dengan β€œ[ css-env-1] " .


Pembaruan 2019-07-06 : Pekerjaan berlanjut pada spesifikasi. Masalah GitHub # 2627 dan Masalah GitHub # 3578 dikhususkan untuk variabel lingkungan khusus dalam kueri media.

Jschoi
sumber
31

Apa yang BISA Anda lakukan adalah @ media meminta: pernyataan root Anda!

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

Sepenuhnya berfungsi di Chrome, Firefox dan Edge setidaknya versi produksi terbaru pada posting ini.

Sean
sumber
Wow terima kasih! Ini pasti jawaban yang benar.
SimplyComplexable
1
Senang mendengarnya. Satu batasan: Jika juga perlu mengakses nilai itu sebagai var, maka dapat digunakan dalam perhitungan di tempat lain dalam css, ini masih memerlukan menempatkan "nilai ajaib" (di sini, 479px) di dua tempat: permintaan media dan deklarasi var.
ToolmakerSteve
8

Ternyata tidak mungkin menggunakan variabel CSS asli seperti itu. Itu salah satu batasannya .

Cara cerdas untuk menggunakannya adalah mengubah variabel Anda dalam kueri media, untuk memengaruhi semua gaya Anda. Saya merekomendasikan artikel ini .

:root {
  --gutter: 4px;
}

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

@media (min-width: 600px) {
  :root {
    --gutter: 16px;
  }
}
Cohars
sumber
Saya tidak mengerti arti "ubah variabel Anda di kueri media", Anda dapat menunjukkan contoh?
1
Bukan itu yang saya maksudkan. Saya bertanya tentang nilai permintaan media.
4
Ya, baru saja melakukannya, itu ada di artikel yang saya tautkan. Saya tahu ini bukan yang Anda harapkan, tetapi variabel CSS tidak dapat digunakan untuk menentukan kueri media
Cohars
8

Salah satu cara untuk mencapai apa yang Anda inginkan adalah menggunakan paket npm postcss-media-variables.

Jika Anda baik-baik saja dengan menggunakan paket npm maka Anda dapat melihat documentatoin untuk hal yang sama di sini

Contoh

/* 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) {}
pradeep1991singh
sumber
4
Terima kasih, tetapi saya mencoba untuk tidak menggunakan preprosesor apa pun.
et. al: Dengan postcss Anda juga dapat menggunakan cssnext cssnext.io/features/#custom-media-queries
sebilasse
1
@sebilasse: custom-media-queries tidak mengatasi masalah utama tidak dapat menggunakan variabel css sebagai breakpoints untuk kueri media
zhirzh
1
postcss bukan preprocessor
1

Karena Anda dapat membaca jawaban lain, masih tidak mungkin melakukannya.

Seseorang disebutkan variabel kustom lingkungan (mirip dengan variabel css kustom env()bukan var()), dan prinsip adalah suara, meskipun masih ada 2 isu utama:

  • dukungan browser yang lemah
  • sejauh ini tidak ada cara untuk mendefinisikannya (tetapi mungkin akan ada di masa depan, karena sejauh ini hanya konsep tidak resmi)
Vojtisek
sumber
1

Jawaban singkat

Anda dapat menggunakan JavaScript untuk mengubah nilai kueri media dan mengaturnya ke nilai variabel 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 = '..'


Jawaban panjang

Saya menulis skrip kecil yang dapat Anda sertakan di halaman Anda. Ini menggantikan setiap aturan media dengan nilai 1pxdengan nilai variabel css --replace-media-1px, aturan dengan nilai 2pxdengan --replace-media-2pxdan sebagainya. Ini bekerja untuk pertanyaan media with, min-width, max-width, height, min-heightdan max-heightbahkan ketika mereka terhubung menggunakan 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) {
  ...
}
Ich_73
sumber