Menggunakan Variabel Sass dengan CSS3 Media Queries

121

Saya mencoba menggabungkan penggunaan variabel Sass dengan kueri @media sebagai berikut:

$base_width:1160px;

@media screen and (max-width: 1170px) {$base_width: 960px;}
@media screen and (min-width: 1171px) {$base_width: 1160px;}

$base_width kemudian ditentukan di berbagai titik dalam pengukuran berbasis persentase lebar stylesheet untuk menghasilkan tata letak yang dapat disesuaikan.

Ketika saya melakukan ini, variabel tampaknya dikenali dengan benar tetapi kondisi untuk kueri media tidak. Misalnya, kode di atas menghasilkan tata letak 1160 piksel terlepas dari lebar layar. Jika saya membalik pernyataan @media seperti ini:

@media screen and (min-width: 1171px) {$base_width: 1160px;}
@media screen and (max-width: 1170px) {$base_width: 960px;}

Ini menghasilkan tata letak 960px, sekali lagi terlepas dari lebar layar. Juga perhatikan bahwa jika saya menghapus baris pertama $base_width: 1160px;itu mengembalikan kesalahan untuk variabel yang tidak ditentukan. Ada ide apa yang saya lewatkan?

Jeremy S.
sumber
Digandakan stackoverflow.com/questions/40739695/...
Serkan KONAKCI

Jawaban:

97

Ini tidak mungkin. Karena pemicunya @media screen and (max-width: 1170px)terjadi di sisi klien.

Mencapai hasil yang diharapkan hanya mungkin jika SASS mengambil semua aturan dan properti di lembar gaya yang berisi $base_widthvariabel Anda dan menyalin / mengubahnya sesuai.

Karena ini tidak akan bekerja secara otomatis, Anda dapat melakukannya dengan tangan seperti ini:

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

Ini tidak benar-benar KERING tetapi yang terbaik yang dapat Anda lakukan.

Jika perubahannya sama setiap kali Anda juga bisa menyiapkan mixin yang berisi semua nilai yang berubah, jadi Anda tidak perlu mengulanginya. Selain itu, Anda dapat mencoba menggabungkan mixin dengan perubahan tertentu. Suka:

@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

Dan Mixin akan terlihat seperti ini

=base_width_changes($base_width)
    #wrapper
        width: $base_width
woerndl.dll
sumber
6
Apakah masih SASS tidak akan bekerja dengan $ variabel di dalam kueri @media?
HappyTorso
1
@HappyTorso akan selalu demikian, sampai ada kompiler Sass sisi klien (misalnya dalam JavaScript) yang berjalan pada pengubahan ukuran viewport. Variabel Sass dikompilasi menjadi nilai statis pada waktu pembuatan; mereka tidak lagi ada saat runtime. Kueri media dievaluasi pada waktu proses, ketika atribut media dalam kueri berubah.
ericsoco
26
@ericsoco Saya tidak mengerti mengapa itu alasan. SASS dapat dengan mudah (?) Melacak semua penggunaan variabel dan memasukkan kueri media di mana mereka digunakan; $foo: 1rem; @media (min-width: 10rem) {$foo: 2rem} .class {font-size: $foo} .class2 {padding: $foo}akan menghasilkan.class {font-size: 1rem} .class2 {padding: 1rem} @media (min-width: 10rem) (.class {font-size: 2rem} .class2 {padding: 2rem}}
powerbuoy
1
ya sass adalah preprocessor, tidak ada alasan untuk "Ini tidak mungkin" ... Itu bisa melakukannya, itu hanya tidak diimplementasikan.
Ini
54

Mirip dengan jawaban Philipp Zedler, Anda dapat melakukannya dengan mixin. Itu memungkinkan Anda memiliki semuanya dalam satu file jika Anda mau.

    @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);
    }
ronen
sumber
1
cepat atau lambat Anda akan menemukan Soal ini, tho: sitepoint.com/cross-media-query-extend-sass
InsOp
Yang ini lebih baik dari jawaban saya!
Philipp Zedler
+1 suka solusi ini. Gabungkan ini dengan peta ( sass-lang.com/documentation/functions/map ) dan Anda memiliki kekuatan - saya akan membuat solusi terpisah untuk menjelaskannya. Edit: selesai. stackoverflow.com/a/56894640/385273
Ben
9

Sunting: Tolong jangan gunakan solusi ini. Jawaban dengan ronen jauh lebih baik.

Sebagai solusi KERING, Anda dapat menggunakan @importpernyataan di dalam kueri media, misalnya seperti ini.

@media screen and (max-width: 1170px) {
    $base_width: 960px;
    @import "responsive_elements";
}
@media screen and (min-width: 1171px) {
    $base_width: 1160px;
    @import "responsive_elements";
}

Anda menentukan semua elemen responsif dalam file yang disertakan menggunakan variabel yang ditentukan dalam kueri media. Jadi, yang perlu Anda ulangi hanyalah pernyataan impor.

Philipp Zedler
sumber
9

Ini tidak mungkin dilakukan dengan SASS, tetapi dapat dilakukan dengan variabel CSS (atau properti khusus CSS ). Satu-satunya kelemahan adalah dukungan browser - tetapi sebenarnya ada plugin PostCSS - postcss-css-variable - yang "meratakan" penggunaan variabel CSS (yang juga memberi Anda dukungan untuk browser lama).

Contoh berikut berfungsi baik dengan SASS (dan dengan variabel postcss-css-Anda mendapatkan dukungan untuk browser lama juga).

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

Ini akan menghasilkan CSS berikut. Kueri media berulang akan meningkatkan ukuran file, tetapi saya telah menemukan bahwa peningkatan biasanya dapat diabaikan begitu server web berlaku gzip(yang biasanya akan dilakukan secara otomatis).

.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;
  }
}
fredrikekelund
sumber
8

Dengan jawaban bagus dari @ ronen dan peta, ada beberapa kekuatan nyata yang tersedia:

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

Sekarang mungkin untuk memiliki lebih banyak penargetan kueri media KERING .myDivdengan sekumpulan nilai berbeda.


Dokumen peta: https://sass-lang.com/documentation/functions/map

Contoh penggunaan peta: https://www.sitepoint.com/using-sass-maps/

Ben
sumber
Saya butuh beberapa saat untuk melihatnya, tetapi ini adalah teknik yang sama dengan jawaban @ ronen, hanya menggunakan input peta untuk mendukung banyak variabel sekaligus. Saya tidak mengurangi nilainya dengan cara apa pun, tetapi lebih sulit untuk memahami sampai saya membuat hubungan itu
John Neuhaus
5

Saya memiliki masalah yang sama.

The $menu-widthvariabel harus 240px pada ponsel pandangan @media only screen and (max-width : 768px)dan 340px pada desktop yang tampilan.

Jadi saya hanya membuat dua variabel:

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

Dan inilah cara saya menggunakannya:

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

Dua rekomendasi

1 Tulis pernyataan CSS "default" Anda untuk layar kecil dan hanya gunakan kueri media untuk layar yang lebih besar. Biasanya tidak diperlukan max-widthkueri media.

Contoh (dengan asumsi elemen memiliki kelas "container")

@mixin min-width($width) {
  @media screen and (max-width: $width) {
    @content;
  }
}

.container {
  width: 960px;

  @include min-width(1170px) {
    width: 1160px;
  }
}

2 Gunakan variabel CSS untuk menyelesaikan masalah, jika Anda bisa .

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

catatan:

Karena akan memiliki lebar 1160px ketika jendela memiliki lebar 1170px, mungkin lebih baik menggunakan lebar 100% dan lebar maksimum 1160px, dan elemen induk mungkin memiliki bantalan horizontal 5px, selama properti ukuran kotak diatur ke kotak-batas. Ada banyak cara untuk memecahkan masalah tersebut. Jika induknya bukan wadah flex atau grid yang bisa Anda gunakan .container { margin: auto }.

Stephen
sumber