CSS3 Medya Sorguları ile Sass Değişkenlerini Kullanma


121

Bir Sass değişkeninin kullanımını @media sorgularıyla aşağıdaki gibi birleştirmeye çalışıyorum:

$base_width:1160px;

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

$base_width daha sonra değişken mizanpajlar oluşturmak için stil sayfası genişlik yüzdesine dayalı ölçümlerin çeşitli noktalarında tanımlanır.

Bunu yaptığımda, değişken doğru bir şekilde tanınıyor gibi görünüyor, ancak medya sorgusu için koşullar geçerli değil. Örneğin, yukarıdaki kod, ekran genişliğinden bağımsız olarak 1160 piksellik bir düzen oluşturur. @Media ifadelerini böyle çevirirsem:

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

Yine ekran genişliğinden bağımsız olarak 960 piksel düzen üretir. Ayrıca, ilk satırını kaldırırsam $base_width: 1160px;tanımsız bir değişken için hata verdiğine dikkat edin . Neyi kaçırdığıma dair bir fikrin var mı?


Yanıtlar:


97

Bu kesinlikle mümkün değil. Tetikleyici @media screen and (max-width: 1170px)istemci tarafında olduğu için.

Beklediğiniz sonuca ulaşmak ancak SASS, $base_widthdeğişkeninizi içeren stil sayfanızdaki tüm kuralları ve özellikleri yakalayıp bunları uygun şekilde kopyalayıp / değiştirdiğinde mümkün olabilir.

Otomatik olarak çalışmayacağından, bunu şu şekilde elle yapabilirsiniz:

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

Bu gerçekten KURU değil ama yapabileceğiniz en iyi şey.

Değişiklikler her seferinde aynıysa, tüm değişen değerleri içeren bir mixin de hazırlayabilirsiniz, böylece tekrarlamanız gerekmez. Ek olarak, karışımı belirli değişikliklerle birleştirmeyi deneyebilirsiniz. Sevmek:

@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

Ve Mixin şöyle görünürdü

=base_width_changes($base_width)
    #wrapper
        width: $base_width

6
Yine de SASS, @media sorguları içinde $ değişkenlerle çalışmayacak mı?
HappyTorso

1
@HappyTorso, görünüm alanı yeniden boyutlandırmada çalışan bir istemci tarafı Sass derleyicisi (örneğin JavaScript'te) olana kadar her zaman böyle olacaktır. Sass değişkenleri, derleme zamanında statik değerlere göre derlenir; artık çalışma zamanında mevcut değiller. Ortam sorguları, sorgudaki ortam öznitelikleri değiştiğinde çalışma zamanında değerlendirilir.
ericsoco

26
@ericsoco Bunun neden bir neden olduğunu anlamıyorum. SASS kolayca (?) Değişkenin tüm kullanımlarını izleyebilir ve kullanıldıkları ortam sorgularını ekleyebilir; $foo: 1rem; @media (min-width: 10rem) {$foo: 2rem} .class {font-size: $foo} .class2 {padding: $foo}sonuçlanacak.class {font-size: 1rem} .class2 {padding: 1rem} @media (min-width: 10rem) (.class {font-size: 2rem} .class2 {padding: 2rem}}
powerbuoy

1
yep sass bir önişlemci, "Bu kesinlikle mümkün değil" için bir sebep yok ... Bunu yapabilir, sadece uygulanmadı.
Ini

54

Philipp Zedler'in cevabına benzer şekilde, bunu bir mixin ile yapabilirsiniz. Bu, isterseniz her şeyi tek bir dosyada elde etmenizi sağlar.

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

1
: er ya da geç bu sorunu, tho karşılaşmak youll sitepoint.com/cross-media-query-extend-sass
InsOp

Bu benim cevabımdan daha iyi!
Philipp Zedler

+1 bu çözüme bayılıyor. Bunu bir harita ile birleştirin ( sass-lang.com/documentation/functions/map ) ve biraz gücünüz var - burada açıklamak için ayrı bir çözüm yapacağım. Düzenleme: tamamlandı. stackoverflow.com/a/56894640/385273
Ben

9

Düzenleme: Lütfen bu çözümü kullanmayın. Ronen'in cevabı çok daha iyi.

DRY çözümü olarak, @importifadeyi bir medya sorgusu içinde kullanabilirsiniz , örneğin bunun gibi.

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

Ortam sorgusunda tanımlanan değişkenleri kullanarak dosyadaki tüm duyarlı öğeleri tanımlarsınız. Yani, tekrarlamanız gereken tek şey import ifadesidir.


9

Bu, SASS ile mümkün değildir, ancak CSS değişkenleri (veya CSS özel özellikleri ) ile mümkündür. Tek dezavantaj, tarayıcı desteğidir - ancak aslında bir PostCSS eklentisi vardır - postcss-css-değişkenleri - CSS değişkenlerinin kullanımını "düzleştirir" (bu size eski tarayıcılar için de destek sağlar).

Aşağıdaki örnek SASS ile harika çalışıyor (ve postcss-css-değişkenleriyle de eski tarayıcılar için destek alıyorsunuz).

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

Bu, aşağıdaki CSS ile sonuçlanır. Tekrarlayan medya sorguları dosya boyutunu artıracaktır, ancak web sunucusu uygulandığında artışın genellikle ihmal edilebilir olduğunu buldum gzip(ki bu genellikle otomatik olarak yapacaktır).

.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;
  }
}

8

@ Ronen'in harika yanıtı ve bir haritayla, gerçek bir güç mevcut:

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

Artık .myDivbir grup farklı değeri hedefleyen çok daha fazla DRY medya sorgusuna sahip olmak mümkün .


Harita belgeleri: https://sass-lang.com/documentation/functions/map

Örnek harita kullanımı: https://www.sitepoint.com/using-sass-maps/


Bunu görmem bir saniyemi aldı, ancak bu @ ronen'in cevabıyla aynı teknik, aynı anda birden fazla değişkeni desteklemek için bir harita girişi kullanıyor. Değerini hiçbir şekilde düşürmüyorum, ancak bu bağlantıyı kurana kadar anlamak daha zordu
John Neuhaus

5

Ben de aynı sorunu yaşadım.

$menu-widthDeğişken üzerinde 240 piksel olmalıdır mobil görünümde @media only screen and (max-width : 768px)ve 340px masaüstü görünümü.

Bu yüzden basitçe iki değişken oluşturdum:

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

Ve işte onu nasıl kullandım:

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

1

İki öneri

1 Küçük ekranlar için "varsayılan" CSS ifadelerinizi yazın ve yalnızca daha büyük ekranlar için medya sorgularını kullanın. Genellikle bir max-widthmedya sorgusuna gerek yoktur .

Örnek (öğenin "kapsayıcı" sınıfına sahip olduğu varsayılarak)

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

.container {
  width: 960px;

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

2 eğer Kullanım CSS değişkenler, sorunu çözmek için yapabilirsiniz .

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

Not:

Pencere 1170 piksel genişliğe sahip olduğunda 1160 piksel genişliğe sahip olacağından,% 100 genişlik ve maksimum 1160 piksel genişlik kullanmak daha iyi olabilir ve ana öğenin yatay dolgusu 5 piksel olabilir. kutu boyutlandırma özelliği border-box olarak ayarlanır. Sorunu çözmenin birçok yolu var. Üst öğe esnek veya ızgara kapsayıcı değilse kullanabilirsiniz .container { margin: auto }.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.