CSS i @media: min-width, max-width - jak/którego używać

0
@import url("/inc/CSS/RWD-0767.css") only screen and (min-width: 576px) and (max-width: 767px);
@import url("/inc/CSS/RWD-0991.css") only screen and (min-width: 768px) and (max-width: 991px);
@import url("/inc/CSS/RWD-1199.css") only screen and (min-width: 992px) and (max-width: 1199px);

Powyżej sposób, w jaki aktualnie podpinam style dla różnych rozmiarów. Mam pytanie z tym związane - trochę czytałem i w necie znalazłem różne techniki/podejścia:

  • stosować (jak wyżej) podawanie obu rozmiarów/jawne określanie przedziałów, dla których dany styl ma obowiązywać (z wyjątkiem dwóch skrajnych, gdzie jest tylko max albo min)
  • podawać tylko max-width dla wszystkich
  • ułożyć style odwrotnie niż w poprzednim punkcie i stosować jedynie min-width

Pytanie - który sposób (i dlaczego) polecacie?

Znalazłem jeszcze gdzieś poradę, aby stosując jednocześnie max i min przy jednej wartości podawać część ułamkową - czyli że jeden przedział ma max-width: 100,90px, a kolejny breakpoint ustawić na min-width: 101px. Podobno ma to sens, bo czasem jak się skaluje to potrafią wyjść ułamkowe wymiary i taki trick jest w stanie spowodować, że nie dojdzie do sytuacji, ze jeden arkusz się kończy na 100px, drugi zaczyna na 101, a ekran mamy 100,75 i żaden styl się nie łapie. Ma to sens? zdarza się to realnie? Przecież jak rozmiar nie spowoduje załapanie się na wyższą regułę, to stosujemy CSS z niższego/mniejszego przedziału, raczej nie dojdzie do sytuacji, w której żaden styl/jakiś z czapy/styl podstawowy się podepnie.

I ostatnia sprawa - tak chcę się upewnić czy dobrze myślę ;) (proszę się nie śmiać, webówka to nie moja działka):
Jeśli nie stosujemy obustronnie domkniętych przedziałów (jak w kodzie widocznym powyżej) tylko max-width albo min-width to umieszczamy style w takiej kolejności, żeby ostatni pasujący został zastosowany? Czyli przykładowo - mamy ekran o szerokości 600px i style z ustawionym min-width na A:300px, B:450, C:500 i D:700px. W takim razie min-szerokość 600px jest spełniona dla przedziałów A, B i C, a ponieważ bierzemy pod uwagę ostatni pasujący warunek, zastosujemy styl C. D odpada, ponieważ tam jest wymagana szerokość przynajmniej 700px, a ekran ma tylko 600. Dobrze rozumiem, czy coś pokręciłem?

2

Ja stosuję zawsze min-width jako mixin ze zdefiniowanymi breakpointami sm, md, lg.... Jeśli przypadek tego wymaga to też max-width, orientation itd.

Tak, zostanie zastosowany styl C. Tak działa podejście mobile first. Ważne, żeby zdefiniować logicznej wielkości breakpointy.
Ja stosuję takie (xs w zasadzie nie jest używane, bo to mobile, więc po prostu w selektorze umieszcza się style):

$grid-breakpoints: (
	xs: 0,
	sm: 576px,
	md: 768px,
	lg: 992px,
	xl: 1200px,
	xxl: 1600px
);
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
	$min: breakpoint-min($name, $breakpoints);

	@if $min {
		@media (min-width: $min) {
			@content;
		}
	}

	@else {
		@content;
	}
}

@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
	$min: map-get($breakpoints, $name);
	@return if($min !=0, $min, null);
}

// Użycie

.product-header {
  font-size: 12px;

  @include media-breakpoint-up(lg) {
    font-size: 14px;
  }

  @include media-breakpoint-up(xl) {
    font-size: 16px;
    line-height: 21px;
  }
}

No dobra może to SCSS, ale już to napisałem XD

1
cerrato napisał(a):
@import url("/inc/CSS/RWD-0767.css") only screen and (min-width: 576px) and (max-width: 767px);
@import url("/inc/CSS/RWD-0991.css") only screen and (min-width: 768px) and (max-width: 991px);
@import url("/inc/CSS/RWD-1199.css") only screen and (min-width: 992px) and (max-width: 1199px);

Powyżej sposób, w jaki aktualnie podpinam style dla różnych rozmiarów. Mam pytanie z tym związane - trochę czytałem i w necie znalazłem różne techniki/podejścia:

  • stosować (jak wyżej) podawanie obu rozmiarów/jawne określanie przedziałów, dla których dany styl ma obowiązywać (z wyjątkiem dwóch skrajnych, gdzie jest tylko max albo min)
  • podawać tylko max-width dla wszystkich
  • ułożyć style odwrotnie niż w poprzednim punkcie i stosować jedynie min-width

Zazwyczaj importowanie styli wewnątrz pliku css jest wolniejsze niż dodanie tego samego przez znacznik <link>. Działa to w mniej więcej taki sposób, że najpierw przeglądarka stara się załadować główny plik, w którym są importy np "rwd.css" i dopiero w kolejnym etapie doładowuje pozostałe części "rwd-0767, rwd-0991, rwd-1199".

Jeśli chciałbym zrobić coś podobnego to zapisałbym to tak

<link rel="stylesheet" href="..." media="screen and (min-width: 768px) and (max-width: 991px)">

Pytanie - który sposób (i dlaczego) polecacie?

U siebie stosuje najczęściej najprostszy wariant, chociaż nie jest najlepszy pod kątem optymalizacji :P

<link rel="stylesheet" href="framework.css">
<link rel="stylesheet" href="slider-lib.css">
<link rel="stylesheet" href="app.css">

i w pliku, który tworzę skupiam się, żeby wszystkie możliwe zapytania @media stosowały sam min-width

body {
  /* ... */
}

@media (min-width: 576px) {
  body {
    /* ... */
  }
}

@media (min-width: 992px) {
  body {
    /* ... */
  }
}

Znalazłem jeszcze gdzieś poradę, aby stosując jednocześnie max i min przy jednej wartości podawać część ułamkową - czyli że jeden przedział ma max-width: 100,90px, a kolejny breakpoint ustawić na min-width: 101px. Podobno ma to sens, bo czasem jak się skaluje to potrafią wyjść ułamkowe wymiary i taki trick jest w stanie spowodować, że nie dojdzie do sytuacji, ze jeden arkusz się kończy na 100px, drugi zaczyna na 101, a ekran mamy 100,75 i żaden styl się nie łapie. Ma to sens? zdarza się to realnie? Przecież jak rozmiar nie spowoduje załapanie się na wyższą regułę, to stosujemy CSS z niższego/mniejszego przedziału, raczej nie dojdzie do sytuacji, w której żaden styl/jakiś z czapy/styl podstawowy się podepnie.

Wydaje mi się, że w nowszych wersjach przeglądarek nie ma takiego problemu i wystarczy, że zdefiniujemy pierwsze zapytanie na min-width: 101px, oraz drugie na max-width: 100px.

I ostatnia sprawa - tak chcę się upewnić czy dobrze myślę ;) (proszę się nie śmiać, webówka to nie moja działka):
Jeśli nie stosujemy obustronnie domkniętych przedziałów (jak w kodzie widocznym powyżej) tylko max-width albo min-width to umieszczamy style w takiej kolejności, żeby ostatni pasujący został zastosowany? Czyli przykładowo - mamy ekran o szerokości 600px i style z ustawionym min-width na A:300px, B:450, C:500 i D:700px. W takim razie min-szerokość 600px jest spełniona dla przedziałów A, B i C, a ponieważ bierzemy pod uwagę ostatni pasujący warunek, zastosujemy styl C. D odpada, ponieważ tam jest wymagana szerokość przynajmniej 700px, a ekran ma tylko 600. Dobrze rozumiem, czy coś pokręciłem?

W takiej sytuacji będą widoczne style z plików A / B / C, ostatni plik C powinien mieć pierwszeństwo przed pozostałymi, ale ważny jest jeszcze rodzaj selektora, oraz użycie / nie użycie !important.

1

Zazwyczaj importowanie styli wewnątrz pliku css jest wolniejsze niż dodanie tego samego przez znacznik <link>

Tak, wiem - ale u mnie te style są bardzo lekkie, a hosting na OVH tak wydajny, że nie ma w związku z tym żadnych odczuwalnych opóźnień. A chcę to mieć zrobione w ten sposób, bo te style mają być używane przy kilku różnych stronach i nie widzę innego rozwiązania, żeby jedną linią w HTML podłączyć wiele bazowych arkuszów - reset, RWD, styl główny itp.

widoczne style z plików A / B / C, ostatni plik C powinien mieć pierwszeństwo przed pozostałymi

Czyli jeśli coś będzie napisane (np. kolor dla elementu <SPAN>) w stylu B i nie zostanie nadpisane w C, to wtedy stosujemy regułę z B, a jak w C też ostylujemy znacznik <SPAN> to w zakresie konfliktu między B a C pierwszeństwo ma C. W sumie - działa to jak "zwykłe" CSS - następne reguły nadpisujące wcześniejsze mają priorytet. OK, dzięki za informację. Myślałem, że w takim przypadku jest brany pod uwagę jedynie ostatni pasujący styl (cały arkusz), a pozostałe są ignorowane.

Wydaje mi się, że w nowszych wersjach przeglądarek nie ma takiego problemu i wystarczy, że zdefiniujemy pierwsze zapytanie na min-width: 101px, oraz drugie na max-width: 100px.

Jeśli to się nie zdarzy to spoko, ale zakładając, że jakaś nietypowa/stara przeglądarka się przeskaluje na 100,45px to mamy problem - nie wchodzi na min 101, na max 100 też się nie łapie. Dlatego chyba lepiej jest jednak nie określać obu rozmiarów, tylko zacząć od najmniejszego breakpointa i lecieć rosnącymi min-width.

To jeszcze takie pytanie - jakie breakpointy uważacie za sensowne? @Xarviel - co sądzisz o wartościach zaproponowanych przez @szafran98 ? Coś byś dodał/zmienił?

2
cerrato napisał(a):

Czyli jeśli coś będzie napisane (np. kolor dla elementu <SPAN>) w stylu B i nie zostanie nadpisane w C, to wtedy stosujemy regułę z B, a jak w C też ostylujemy znacznik <SPAN> to w zakresie konfliktu między B a C pierwszeństwo ma C. W sumie - działa to jak "zwykłe" CSS - następne reguły nadpisujące wcześniejsze mają priorytet. OK, dzięki za informację. Myślałem, że w takim przypadku jest brany pod uwagę jedynie ostatni pasujący styl (cały arkusz), a pozostałe są ignorowane.

Dokładnie o to mi chodziło

To jeszcze takie pytanie - jakie breakpointy uważacie za sensowne? @Xarviel - co sądzisz o wartościach zaproponowanych przez @szafran98 ? Coś byś dodał/zmienił?

szafran98 napisał(a):
$grid-breakpoints: (
	xs: 0,
	sm: 576px,
	md: 768px,
	lg: 992px,
	xl: 1200px,
	xxl: 1600px
);

https://getbootstrap.com/docs/5.0/layout/containers/

U siebie stosuje przedziały z bootstrapa (https://getbootstrap.com/docs/5.0/layout/containers/) nawet jak nie jest używany w projekcie, ponieważ się do nich przyzwyczaiłem :P

I resztę dodaje w zależności od potrzeb, ale przeważnie jest to coś w okolicach ekranów full hd

$breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px,
  xxl: 1400px,
  full-hd: 1920px, 
);

@mixin media-up($breakpoint-min) {
  $min: map-get($breakpoints, $breakpoint-min);

  @if ($min >= 0) {
    @media (min-width: $min) {
      @content;
    }
  } @else {
    @content;
  }
}

@mixin media-down($breakpoint-max) {
  $max: map-get($breakpoints, $breakpoint-max) - 1px;

  @if ($max >= 0) {
    @media (max-width: $max) {
      @content;
    }
  } @else {
    @content;
  }
}

@mixin media-only($breakpoint-min, $breakpoint-max) {
  $min: map-get($breakpoints, $breakpoint-min);
  $max: map-get($breakpoints, $breakpoint-max) - 1px;

  @if ($min >= 0 AND $max >= $min) {
    @media (min-width: $min) AND (max-width: $max) {
      @content;
    }
  } @else {
    @content;
  }
}
2

Nie mogę Ci opisać wszystkich za i przeciw; ale mogę Ci opowiedzieć jak ja podchodzę do tematu.

Na wstępie powiem czym się kieruję i co jest dla mnie ważne przy pisaniu takich styli: a więc dla mnie jest najważniejsze żeby było prosto - łatwo, spójnie, żeby wprowadzanie zmian w takim systemie było proste, szybkie i bezkonfliktowe. Staram się unikać cudowania i wprowadzania dodatkowych mechanizmów, jeśli mogę tego uniknąć. Widziałem odpowiedź z generowaniem media query w sasie - dla mnie to byłaby ostateczność, nie zrobiłbym tego chyba że nie miałbym innej opcji. Ja tworząc swoje witryny (np teraz pracuję nad prototypem nowej strony dokumentacji dla t-regx), w 99.9% jestem w stanie ogarnąć całą stronę zwykłymi media query. Staram się unikać komplikacji.

tl;dr; Ja stosuję tylko min-width, i nic więcej; Ale nie jest to żadna "złota zasada", tylko zwykły pragmatyzm.

Kiedy tworzę witryny, to podchodzę do tego mobile-first. I od razu muszę rzucić mokry koc na ogień off-topu który się tutaj rzuca, większość ludzi nie rozumie o co chodzi z mobile-first, więc może opowiem co ja przez to rozumiem - co ma sens. Otóż większość ludzi kiedy słyszy termin "mobile-first" to wydaje im się że to chodzi o "projektowanie najpierw strony na mobilki, potem na desktop" oraz że "projektowanie" oraz "implementowanie" to jedno i to samo. To jest jednak błąd (według mnie). Projektować stronę (np tworzyć szablon, rozmiary, style, kolory, schematy, czcionki) należy najpierw na platformę główną (czyli w 99% to będzie desktop), a potem projektować pomniejsze żeby były w zgodzie z główną - czyli najczęściej projektuje się strony począwszy od desktopa, przez mniejsze rozdzielczości. Mobile-first odnosi się jednak do implementacji, czyli jak już mamy gotowy szablon, to wtedy implementujemy od namniejszych w górę - o to chodzi w mobile first.

Teraz jak ja programuję:

  • krok pierwszy: najpierw wychodzę od szablonu (który sam zaprojektowałem lub znalazłem), ustawiam w chrome/przeglądarce rozdzielczość powiedzmy 200-300px, i układam HTML'a oraz CSS - implementuję witrynę, martwiąc się tylko i wyłącznie tym jak ona wygląda na telefonie. Jak już cała wersja mobilna wygląda dobrze, to uznaję etap "mobilek" za zakończony - ten widok się już nie zmieni.
  • krok drugi, zwiększam lekko szerokość okna przeglądarki (np do 350-400px) i patrzę czy nic się nie rozjechało, i strona nadal wygląda dobrze, czy nie ma za dużo jakichś wolnych przestrzeni, czy jakichś elementów nie można ustawić obok siebie. Jeśli wszystko jest git, to nie dodaję nic. Jeśli po zmianie szerokości coś się zepsuło/rozjechało/wygląda źle; to dodaję media query min-width (od najmniejszej szerokości w jakiej coś przestaje działać), i piszę styl który fixuje wygląd. Może być że wiele dodatkowych styli trzeba dodać.
    • Tutaj jest pierwszy etap gdzie style "sobie wchodzą w drogę", tzn domyślnie element ma np display:block, a ja na wyższej rozdzielczości ustawiam display: flex - ja to uznaję za całkowicie normalne, i nie "poprawiam" tamtego poprzedniego stylu, nie piszę max-width żeby "zabrać" tamten display:block. Posługuję się specyfiką selektorów CSS żeby zadbać o to żeby styl się nadpisał. Robię do dlatego, że chcę uznać poprzedni etap za "zakończony" i mieć pewność że on się nie zepsuję - jakbym zaczął "poprawiać" poprzednie style, mógłbym coś popsuć.
  • Następnie kontyunuje dalej:
    • Zwiększam rozdzielczość, przeklikuję całą aplikację i sprawdzam czy coś się nie rozjechało lub coś wymaga poprawy, żeby pasowało do szablonu - jeśli znajdę takie miejsce to dodaje kolejne min-width i nadpisuję style.
    • Powtarzam proces do największej wspieranej rozdzielczości, czyli najczęściej 2000px szerokości około.

Z takim podejściem nigdy nie trzeba używać max-width, i wszystkie style są zakodzone mobile-first, czyli począwszy od mobilek. Wcześniej pisałem od desktopów w dół (wtedy były same max-width, i żadnego min-width) ale zauważyłem że jakoś więcej wychodzi tych styli wtedy. Nie potrafię tego wytłumaczyć, ale jak się zaczyna od mobilek to tych media query jakoś tak wychodzi mniej, nie wiem czemu tak jest.

Według mnie takie podejście generuje kod, który jest prosty do pisania, prosty do edycji, i co najważniejsze prosty do zrozumienia, bo możemy założyć że każdy styl działa "od teraz w górę" i tyle, bardzo ułatwia to analize kodu i "daje odpocząć mózgowi" od ciągłej analizy na "w którą stronę działa styl". Owszem, czasem się zdarzą przypadki, że jakiś styl trzeba będzie włączyć i wyłączyć kilka razy, ale to są dosyć rzadkie przypadki, i jak wziąć sumarycznie za i przeciw; to zalet dla mnie jest zdecydowanie więcej.

0

Odgrzebujemy temat ;)

Odniosę się do tego, co napisał @Riddle powyżej (ale oczywiście - komentarze mile widziane ze strony wszystkich, nie tylko @Riddle)
Tak nie do końca rozumiem sens zaczynania od małego układu, jeśli piszesz, że docelowym/najczęściej używanym będzie duży desktop.
Poniżej dałem przykładowy układ nagłówka strony - żebyśmy gadali o konkretach:

  • A i G to ustalone na sztywno marginesy
  • B: logo
  • C i E: dystanse, między elementami, które się dopasowują do szerokości ekranu
  • D i F: treści, które mają stałą szerokość

I teraz - to, co widzimy to układ docelowy, jaki będzie na dużym ekranie. Potem, wraz ze zmniejszaniem, będzie się on w pewien sposób zmieniać:

  • czcionka sekcji D i F się zmniejszy
  • marginesy A i G się zmniejszą, a w końcu w ogóle znikną
  • poniżej jakiegoś breakpointa zniknie adres (F), a na zupełnie malutkim ekranie wypadnie także telefon (D)

Robiąc to w sposób, jaki zaproponowałeś - zaczynam od małego ekranu mobilka, więc mam tylko logo, a wszystko ukryte. Potem sobie ekran powiększam i patrzę, co się dzieje. Nie rozumiem tego podejścia, dla mnie logika nakazuje zrobić odwrotnie - robię sobie ukłąd główny/docelowy i powoli go zmniejszam. W pewnym momencie dochodzę do wniosku, że robi się ciasno - wtedy coś zmniejszam, albo wskazuję, ze jakiś fragment nie ma się wyświetlać. I tak zmniejszam wywalając rzeczy w danej rozdzielczości niepotrzebne, aż w wersji na komórkę zostanie mi takie niezbędne minimum.

screenshot-20230316132151.png

Poza tym jeszcze parę pytań natury filozoficznej ;)

  1. jak robicie z pewnymi ogólnymi rzeczami, które się nie zmieniają niezależnie od szerokości (np. krój czcionki, kolor tła itp) - czy dajecie to do głównego pliku CSS, czy wpisujecie do breakpointa, który ZAWSZE będzie pasować, a może osobny styl dołączony przez @import?
  2. Jeśli przyjmiemy mój sposób widzenia - czyli układam sobie najpierw układ duży, a potem schodzę w dół i ukrywam albo przestawiam elementy, to jak będzie lepiej ustawić poszczególne media query? Czy dać od najmniejszego do największego (w zakresie rozmiaru ekranu) i jako kryterium stosowania dać min width, czy odwrotnie - najpierw duży ekran, pod nim mniejsze rozdziałki i zastosować max-width?
  3. jak w poprzednich postach wyjaśnił mi @Xarviel - style są parsowane od góry do dołu i jeśli są jakieś sprzeczności, to zostaje zastosowana ta deklaracja, która się pojawiła jako ostatnia. Dlatego ja bym widział to tak, że w stylach daję najpierw największy breakpoint, a potem podaję wygląd dla mniejszych rozmiarów. W tej sposób jeśli żaden mniejszy się nie załapie, to stosujemy największy breakpoint. Jeśli w jakiejś rozdzielczości chcę coś zmienić, to poprawiam jedynie to, co chcę zmodyfikować. Ta graniczna rozdziałka się załapie jako ostatnia przy media query, więc wcześniejsze style zostaną nadpisane, za to późniejsze się nie załapią, bo będzie podana min-width, która spowoduje, że się one nie łapią.
  4. Jeśli przyjąć że to, co napisałem powyżej ma sens - czy w ogóle jest sens tworzyć osobny styl ze stałymi elementami (czyli to, co pisałem w pkt.1) czy uznać, że pierwszy/największy styl jest takim szablonem domyślnym? Mi się wydaje, że jednak dobrze to dać - bo jeśli np. będę chciał dodać jeszcze jakiś breakpoint szerszy niż aktualnie największy, to się to trochę pokomplikuje. A tak to mam ogólne zasady w "głównym" arkuszu, a te dopasowane do rozmiarów jedynie aktualizują wcześniejsze deklaracje.

1 użytkowników online, w tym zalogowanych: 0, gości: 1