Czy rozmiar multimediów może zmieniać rozmiar na podstawie elementu div zamiast ekranu?

317

Chciałbym użyć zapytań o media, aby zmienić rozmiar elementów na podstawie rozmiaru divelementu, w którym się znajdują. Nie mogę użyć rozmiaru ekranu, ponieważ divjest on po prostu używany jako widżet na stronie internetowej, a jego rozmiar może się różnić.

Aktualizacja

Wygląda na to, że obecnie trwają prace: https://github.com/ResponsiveImagesCG/cq-demos

Yazz.com
źródło
2
Myślę, że to pytanie jest zbyt krótkie, aby uzyskać dobrą odpowiedź. Być może mógłbyś podać przykład tego, co próbujesz zrobić? Może skorzystaj z jsfiddle.net, aby przetestować swój pomysł i pozwolić innym pomóc? Zasadniczo nie powinno być żadnego powodu do tego, o co pytasz, powinieneś być w stanie osiągnąć pożądane wyniki z CSS bez zapytań o media. Możesz użyć wymiarów procentowych i ems dla czcionek do skalowania zagnieżdżonych elementów. Ale może muszę po prostu zobaczyć przykład kodu HTML i CSS, aby lepiej zrozumieć?
BenSwayne,
1
Jak może się różnić rozmiar widżetu? Czy twoja strona ma stałą szerokość (na przykład 960px) z obszarami wyświetlania powyżej 1024px, czy obie są płynne? To jest niejasne i warto byłoby wiedzieć
FelipeAls,
3
W rzeczywistości mój obecny projekt ma podobną sytuację. Lista elementów jest wyświetlana w układzie 2-kolumnowym dla szerokich urządzeń lub 1-kolumnowym dla wąskich urządzeń, ale pojedynczy element będzie w układzie 1-kolumnowym bez względu na wszystko. Zarówno lista, jak i pojedyncza wersja mają 2 elementy, które są dość szerokie i krótkie. W przypadku szerszych urządzeń te 2 elementy wyglądają najlepiej obok siebie. Idealnie wąskie urządzenia: zawsze pionowe, szerokie urządzenia: zawsze równoległe, gdzieś pomiędzy (w zależności od 1 lub 2 kolumn): pionowe lub równoległe. Pływanie to proste rozwiązanie, ale szerokość musi się również różnić w zależności od układu.
cimmanon,
1
LESS zostanie skompilowany do CSS, więc jeśli CSS go nie obsługuje, LESS też nie może ci pomóc.
jvannistelrooy
3
Link nie jest już aktywny?
mix3d

Odpowiedzi:

228

Nie, zapytania multimedialne nie są zaprojektowane do działania w oparciu o elementy na stronie. Są zaprojektowane do pracy w oparciu o urządzenia lub typy mediów (dlatego nazywane są zapytaniami o media ). width, heighti inne funkcje multimedialne oparte na wymiarach odnoszą się do wymiarów rzutni lub ekranu urządzenia w mediach ekranowych. Nie można ich używać do odwoływania się do określonego elementu na stronie.

Jeśli musisz zastosować style w zależności od rozmiaru określonego divelementu na swojej stronie, będziesz musiał użyć JavaScript, aby obserwować zmiany wielkości tego divelementu zamiast zapytań o media.

BoltClock
źródło
Słyszałem o pewnym sposobie używania funkcji zapytań o media w celu uzyskania rozmiaru z elementu zawierającego. Czy jest jakiś sposób, aby połączyć to z zapytaniami o media, aby zmienić rozmiar elementów?
Yazz.com,
1
Będziesz musiał użyć JS, aby okresowo uzyskać szerokość elementu i odpowiednio zareagować (okresowo = co sekundę lub to spowolni niektóre przeglądarki; odpowiednio = przełączając klasy stylizujące widżet, jeśli chcesz najszybszą metodę).
FelipeAls,
6
Aby to osiągnąć natywnie, potrzebowalibyśmy @elementzapytań. W3C ma dobrą dokumentację dotyczącą rymu / przyczyny @mediazapytań: w3.org/TR/css3-mediaqueries/#width (ten link prowadzi do sekcji omawiającej szerokości --- szerokości typu nośnika, a nie zawartych w nim elementów)
Dawson,
Czy jest jakaś szansa, że ​​zadziała w e-mailach? Próbuję zastosować stylizację mobilną do wiadomości e-mail, gdy div kontenera jest zbyt mały (tj. Gdy przestrzeń e-mail w wersji Gmaila na komputer jest zbyt mała, aby zmieściła się w 2 kolumnach, na przykład ze względu na zmianę rozmiaru okna).
Lev
Nawiasem mówiąc, zapytania @element sprawiłyby, że css byłby kompletnym językiem Turinga
Nick
117

Właśnie stworzyłem podkładkę javascript, aby osiągnąć ten cel. Spójrz, jeśli chcesz, to dowód koncepcji, ale uważaj: to wczesna wersja i wciąż wymaga trochę pracy.

https://github.com/marcj/css-element-queries

Marc J. Schmidt
źródło
5
Dzięki, jestem pod wrażeniem
Yazz.com
5
To jest niesamowite. W połączeniu z responsywnym bootstrapem robię niesamowite rzeczy, których nie da się osiągnąć dzięki @media. Dobra robota.
Aku
3
Uratowałeś nam życie
Broda Noel
Wow, naprawdę fajnie, sprawia, że ​​jest o wiele łatwiej
Kaiser
Fajne. Masz pytanie Jak ten wykrywacz wtyczek wykrywa - jakie elementy wymagają min-widthodnowienia atrybutu; czy muszę ręcznie pisać listę klas css, zaznaczone elementy, włączyć min-widthodnawianie?
Alexander Goncharov,
38

Zapytanie o media wewnątrz elementu iframe może działać jako zapytanie elementu. Z powodzeniem to zaimplementowałem. Pomysł zrodził się z ostatniego postu na temat Responsive Ads autorstwa Zurb. Bez Javascript!

haddnin
źródło
myślę, że to najlepsze rozwiązanie, ponieważ zapytania o media działają w ramce iframe.
emfi
25

Obecnie nie jest to możliwe w przypadku samego CSS, ponieważ @BoltClock napisał w zaakceptowanej odpowiedzi, ale można to obejść, używając JavaScript.

Utworzyłem zapytanie kontenerowe (inaczej kwerenda elementowa) prolyfill, aby rozwiązać ten problem. Działa nieco inaczej niż inne skrypty, więc nie musisz edytować kodu HTML swoich elementów. Wszystko, co musisz zrobić, to dołączyć skrypt i użyć go w swoim CSS w następujący sposób:

.element:container(width > 99px) {
    /* If its container is at least 100px wide */
}

https://github.com/ausi/cq-prolyfill

ausi
źródło
2
Jest pełen JS. Celem jest posiadanie funkcjonalności tylko w CSS.
Zielony
13
Prolyfills (i polifill ) są zwykle napisane w JS, aby włączyć funkcję, która nie jest jeszcze obsługiwana przez przeglądarkę. Celem prolyfill jest utrata ważności, gdy ta funkcja będzie obsługiwana w CSS.
ausi
3
@ius w pytaniu nie ma wzmianki o „tylko CSS”. Jak doszedłeś do tego wniosku?
ausi
1
@ius, chyba że nie możesz tego zrobić w CSS, więc oferowanie rozwiązania poza css jest całkowicie rozsądne. O wiele lepsze niż „no can cant”, nie sądzisz;)
Wesley Smith,
1
@ DelightedD0D po moim komentarzu zmienił odpowiedź i głosowałem +1 za zmianą. Obecna odpowiedź jest dla mnie w porządku, ponieważ mówi, że nie jest to możliwe tylko z CSS.
ius
17

Kilka lat temu napotkałem ten sam problem i sfinansowałem opracowanie wtyczki, która pomogłaby mi w pracy. Udostępniłem wtyczkę jako oprogramowanie typu open source, aby inni również mogli z niej skorzystać. Możesz ją pobrać na Github: https://github.com/eqcss/eqcss

Istnieje kilka sposobów zastosowania różnych responsywnych stylów w oparciu o to, co wiemy o elemencie na stronie. Oto kilka elementów zapytania, które wtyczka EQCSS pozwoli Ci pisać w CSS:

@element 'div' and (condition) {
  $this {
    /* Do something to the 'div' that meets the condition */
  }
  .other {
    /* Also apply this CSS to .other when 'div' meets this condition */
  }
}

Więc jakie warunki są obsługiwane dla elastycznych stylów z EQCSS?

Zapytania dotyczące wagi

  • min. szerokość w px
  • min. szerokość w %
  • maksymalna szerokość w px
  • maksymalna szerokość w %

Zapytania o wysokość

  • min. wysokość w px
  • min. wysokość w %
  • maksymalna wysokość w calach px
  • maksymalna wysokość w calach %

Policz zapytania

  • min-znaków
  • maksymalna liczba znaków
  • min-linie
  • max-linie
  • min-dzieci
  • dzieci max

Specjalne selektory

Wewnątrz zapytań o elementy EQCSS można również użyć trzech specjalnych selektorów, które pozwalają bardziej szczegółowo zastosować swoje style:

  • $this (elementy odpowiadające zapytaniu)
  • $parent (elementy nadrzędne elementów odpowiadających zapytaniu)
  • $root(element główny dokumentu <html>)

Zapytania o elementy pozwalają ci skomponować układ z indywidualnie reagujących modułów projektowych, każdy z odrobiną samoświadomości tego, jak są wyświetlane na stronie.

Dzięki EQCSS możesz zaprojektować jeden widżet, który będzie wyglądał dobrze od szerokości 150 pikseli aż do 1000 pikseli, a następnie możesz śmiało upuścić ten widget na dowolnym pasku bocznym na dowolnej stronie przy użyciu dowolnego szablonu (na dowolnej stronie) i

innovati
źródło
1
Niezły projekt!
Rzuciłem
@innovati Znalazłem ten post, szukając sposobu na zapytania o elementy. Nie mogę sprawić, żeby zadziałało. Czy mógłbyś spojrzeć na mój bilet? github.com/eqcss/eqcss/issues/96
Andrew Newby
10

Z perspektywy układu jest to możliwe przy użyciu nowoczesnych technik.

Składa się (jak sądzę) Heydon Pickering. Szczegółowo opisuje proces tutaj: http://www.heydonworks.com/article/the-flexbox-holy-albatross

Chris Coyier podnosi go i przegląda tutaj: https://css-tricks.com/putting-the-flexbox-albatross-to-real-use/

Aby ponownie przedstawić problem, poniżej widzimy 3 tego samego komponentu, każdy złożony z trzech pomarańczowych div oznaczonych a, bi c.

Bloki dwóch drugich są wyświetlane w pionie, ponieważ są ograniczone do poziomego pomieszczenia, a górne komponenty 3 bloki są ułożone poziomo.

Wykorzystuje flex-basiswłaściwość CSS i Zmienne CSS do stworzenia tego efektu.

Ostatni przykład

.panel{
  display: flex;
  flex-wrap: wrap;
  border: 1px solid #f00;
  $breakpoint: 600px;
  --multiplier: calc( #{$breakpoint} - 100%);
  .element{
    min-width: 33%;
    max-width: 100%;
    flex-grow: 1;
    flex-basis: calc( var(--multiplier) * 999 );
  }
}

Próbny

Artykuł Heydona zawiera 1000 słów szczegółowo go wyjaśniających i bardzo polecam lekturę.

Djave
źródło
Ta rzecz z artykułu Heydona ... Wygląda i działa jak magia! Dziękuję za odpowiedź, jest niesamowita.
ptyskju
2
To jest odpowiedź, której wszyscy szukają tego pytania
TehShrike
7

Pytanie jest bardzo niejasne. Jak mówi BoltClock, zapytania o media znają tylko wymiary urządzenia. Można jednak używać zapytań o media w połączeniu z selektorami opuszczania w celu wykonania regulacji.

.wide_container { width: 50em }

.narrow_container { width: 20em }

.my_element { border: 1px solid }

@media (max-width: 30em) {
    .wide_container .my_element {
        color: blue;
    }

    .narrow_container .my_element {
        color: red;
    }
}

@media (max-width: 50em) {
    .wide_container .my_element {
        color: orange;
    }

    .narrow_container .my_element {
        color: green;
    }
}

Jedyne inne rozwiązanie wymaga JS.

Cimmanon
źródło
47
Pytanie wcale nie jest niejasne. W rzeczywistości jest to bardzo dobre pytanie. Niestety nie ma na to dobrej odpowiedzi.
stepanian
2
Straszna konserwacja przy użyciu tego podejścia.
Totty.js,
4

Jedynym sposobem, w jaki mogę myśleć, że możesz osiągnąć to, co chcesz wyłącznie za pomocą css, jest użycie pojemnika z płynem dla widgetu. Jeśli szerokość kontenera jest procentem ekranu, możesz użyć zapytań o media, aby stylizować w zależności od szerokości kontenera, ponieważ teraz będziesz wiedział dla wymiarów każdego ekranu, jakie są wymiary kontenera. Załóżmy na przykład, że decydujesz się na 50% szerokości ekranu kontenera. Następnie dla szerokości ekranu 1200px wiesz, że twój pojemnik ma 600px

.myContainer {
  width: 50%;
}

/* you know know that your container is 600px 
 * so you style accordingly
*/
@media (max-width: 1200px) { 
  /* your css for 600px container */
}
Roumelis George
źródło
Nie, na ekranie wygląda brzydko. Rozmiar ekranu zmienia się szybciej, ale element pojawia się na ekranie później i jest mniejszy.
Zielony
3

Myślałem również o zapytaniach medialnych, ale potem znalazłem to:

Wystarczy utworzyć opakowanie <div>z wartością procentową dla padding-bottom:

div {
  width: 100%;
  padding-bottom: 75%;
  background:gold; /** <-- For the demo **/
}
<div></div>

Spowoduje to, że <div>wysokość będzie równa 75% szerokości pojemnika (współczynnik kształtu 4: 3).

Technikę tę można również łączyć z zapytaniami o media i odrobiną wiedzy ad hoc na temat układu strony, aby uzyskać jeszcze bardziej szczegółową kontrolę.

To wystarczy na moje potrzeby. Co może być wystarczające również dla twoich potrzeb.

Hendy Irawan
źródło
2

Możesz użyć interfejsu API ResizeObserver . Nadal jest na początku, więc nie jest jeszcze obsługiwany przez wszystkie przeglądarki (ale jest kilka polifillów, które mogą ci w tym pomóc).

Zasadniczo ten interfejs API umożliwia dołączenie detektora zdarzeń do zmiany rozmiaru elementu DOM.

Demo 1 - Demo 2

José Salgado
źródło
Istnieje specyfikacja wypełnienia dla specyfikacji projektu. github.com/juggle/resize-observer
Trevor Karjanis
Artykuł Heydona zawiera przykładową implementację tego. Wyszukaj „ResizeObserver” na stronie: heydonworks.com/article/the-flexbox-holy-albatross
Gabe Rogan
0

W przypadku mojego zrobiłem to, ustawiając maksymalną szerokość div, dlatego dla małego widgetu nie będzie to miało wpływu, a duży widget zostanie przeskalowany ze względu na styl maksymalnej szerokości.

  // assuming your widget class is "widget"
  .widget {
    max-width: 100%;
    height: auto;
  }
Jacky Choo
źródło
Pytanie wspomniało, że rozmiar widgetu może się różnić, ustawienie maksymalnej szerokości nie zmieni rozmiaru widgetu, gdy kontener jest szeroki. .widgetjest tylko próbką jako klasą div widgetu.
Jacky Choo,