Können Medienabfragen basierend auf einem div-Element anstelle des Bildschirms in der Größe geändert werden?

317

Ich möchte Medienabfragen verwenden, um die Größe von Elementen basierend auf der Größe eines divElements zu ändern, in dem sie sich befinden. Ich kann die Bildschirmgröße nicht verwenden, da sie divnur wie ein Widget auf der Webseite verwendet wird und ihre Größe variieren kann.

Aktualisieren

Anscheinend wird derzeit daran gearbeitet: https://github.com/ResponsiveImagesCG/cq-demos

Yazz.com
quelle
2
Ich denke, diese Frage ist zu kurz, um eine gute Antwort zu bekommen. Vielleicht könnten Sie ein Beispiel dafür geben, was Sie versuchen zu tun? Vielleicht verwenden Sie jsfiddle.net , um Ihre Idee zu testen und anderen zu erlauben, Ihnen zu helfen? Im Allgemeinen sollte es keinen Grund für Ihre Anfrage geben. Sie sollten in der Lage sein, die gewünschten Ergebnisse mit CSS ohne Medienabfragen zu erzielen. Sie können prozentuale Abmessungen und ems für Schriftarten verwenden, um verschachtelte Elemente zu skalieren. Aber vielleicht muss ich nur ein Beispiel für Ihren HTML-Code und Ihr CSS sehen, um es besser zu verstehen?
BenSwayne
1
Wie kann die Größe Ihres Widgets variieren? Ist Ihre Seitenbreite (Beispiel 960 Pixel) mit Ansichtsfenstern über 1024 Pixel fest oder sind beide flüssig? Das ist unklar und wäre nützlich zu wissen
FelipeAls
3
Eigentlich hat mein aktuelles Projekt eine ähnliche Situation. Eine Liste von Elementen wird in einem 2-Spalten-Layout für breite Geräte oder einem 1-Spalten-Layout für schmale Geräte angezeigt, aber ein einzelnes Element wird in einem 1-Spalten-Layout angezeigt, egal was passiert. Sowohl die Liste als auch die Einzelversion enthalten zwei Elemente, die ziemlich breit und kurz sind. Bei breiteren Geräten sehen die beiden Elemente am besten nebeneinander aus. Idealerweise schmale Geräte: immer vertikal, breite Geräte: immer parallel, irgendwo dazwischen (je nach 1 oder 2 Spalten): vertikal oder parallel. Floating ist die einfache Lösung, aber die Breite muss auch je nach Layout variieren.
Cimmanon
1
LESS wird zu CSS kompiliert. Wenn CSS dies nicht unterstützt, kann LESS Ihnen auch nicht helfen.
Jvannistelrooy
3
Link nicht mehr aktiv?
mix3d

Antworten:

227

Nein, Medienabfragen funktionieren nicht basierend auf Elementen auf einer Seite. Sie sind so konzipiert, dass sie auf Geräten oder Medientypen basieren (daher werden sie als Medienabfragen bezeichnet ). width,, heightund andere dimensionsbasierte Medienfunktionen beziehen sich alle auf die Abmessungen des Ansichtsfensters oder des Gerätebildschirms in bildschirmbasierten Medien. Sie können nicht verwendet werden, um auf ein bestimmtes Element auf einer Seite zu verweisen.

Wenn Sie Stile abhängig von der Größe eines bestimmten divElements auf Ihrer Seite anwenden müssen , müssen Sie JavaScript verwenden, um Änderungen in der Größe dieses divElements anstelle von Medienabfragen zu beobachten .

BoltClock
quelle
Ich habe gehört, dass ich möglicherweise Funktionen mit Medienabfragen verwenden kann, um die Größe eines enthaltenen Elements zu ermitteln. Gibt es eine Möglichkeit, dies mit Medienabfragen zu kombinieren, um die Größe von Elementen zu ändern?
Yazz.com
1
Sie müssten JS verwenden, um regelmäßig die Breite Ihres Elements zu ermitteln und entsprechend zu reagieren (periodisch = jede Sekunde oder so, oder es verlangsamt einige Browser; entsprechend = durch Umschalten der Klassen, die Ihr Widget gestalten, wenn Sie die schnellste Methode wünschen).
FelipeAls
6
Um dies nativ zu erreichen, benötigen wir @elementAbfragen. W3C hat einige gute Dokumentationen zum Reim / Grund für @mediaAbfragen: w3.org/TR/css3-mediaqueries/#width (dieser Link führt Sie zu dem Abschnitt über Breiten --- Breiten des Medientyps, nicht zu den darin enthaltenen Elementen).
Dawson
Gibt es eine Chance, dass es in E-Mails funktioniert? Ich versuche, das mobile Styling auf E-Mails anzuwenden, wenn der Container div zu klein ist (dh wenn der E-Mail-Speicherplatz der Google Mail-Desktopversion zu klein ist, um in ein zweispaltiges Design zu passen, beispielsweise aufgrund der Größenänderung des Fensters).
Lev
Übrigens, @element-Abfragen würden CSS zu einer vollständigen Turing-Sprache machen
Nick
117

Ich habe gerade ein Javascript-Shim erstellt, um dieses Ziel zu erreichen. Werfen Sie einen Blick darauf, wenn Sie möchten, es ist ein Proof-of-Concept, aber seien Sie vorsichtig: Es ist eine frühe Version und benötigt noch etwas Arbeit.

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

Marc J. Schmidt
quelle
5
Vielen Dank, ich bin beeindruckt
Yazz.com
5
Das ist unglaublich. In Kombination mit reaktionsschnellem Bootstrap mache ich einige großartige Dinge, die mit @media nicht erreicht werden konnten. Gut gemacht.
Aku
3
Du hast unser Leben gerettet
Broda Noel
Wow, wirklich nett, macht die Sache viel einfacher
Kaiser
Cool. Habe die Frage. Thisow dieses Plugin erkennt - welche Elemente müssen min-widthAttribute erneuert werden; Muss ich manuell eine CSS-Klassenliste schreiben, markierte Elemente, die zur min-widthErneuerung aktiviert sind ?
Alexander Goncharov
38

Eine Medienabfrage innerhalb eines Iframes kann als Elementabfrage fungieren. Ich habe dies erfolgreich implementiert. Die Idee stammt aus einem kürzlich veröffentlichten Beitrag über Responsive Ads von Zurb. Kein Javascript!

haddnin
quelle
Ich denke, dies ist die beste Lösung, da die Medienabfragen innerhalb des Iframes funktionieren.
EMFI
25

Dies ist derzeit mit CSS allein nicht möglich, wie @BoltClock in der akzeptierten Antwort geschrieben hat. Sie können dies jedoch mithilfe von JavaScript umgehen.

Ich habe eine Containerabfrage (auch als Elementabfrage bezeichnet) erstellt, um diese Art von Problem zu lösen. Es funktioniert etwas anders als andere Skripte, sodass Sie den HTML-Code Ihrer Elemente nicht bearbeiten müssen. Alles, was Sie tun müssen, ist, das Skript einzuschließen und es wie folgt in Ihrem CSS zu verwenden:

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

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

ausi
quelle
2
Es ist voll von JS. Ziel ist es, die Funktionalität nur in CSS zu haben.
Grün
13
Prolyfills (und Polyfills ) werden normalerweise in JS geschrieben, um eine Funktion zu aktivieren, die vom Browser noch nicht unterstützt wird. Das Ziel der Prolyfill ist es, veraltet zu werden, sobald diese Funktion in CSS unterstützt wird.
Ausi
3
@ius es gibt keine Erwähnung von "nur CSS" in der Frage. Wie sind Sie zu diesem Schluss gekommen?
Ausi
1
@ius außer Sie kippt es möglicherweise in CSS tut so eine Lösung außerhalb von CSS bietet durchaus sinnvoll ist. Viel besser als "nein du kannst nicht", meinst du nicht;)
Wesley Smith
1
@ DelightedD0D Nach meinem Kommentar hat er die Antwort geändert und ich habe +1 für die Änderung gestimmt. Die aktuelle Antwort ist für mich in Ordnung, da ich weiß, dass dies nicht nur mit CSS möglich ist.
Ius
17

Ich bin vor ein paar Jahren auf dasselbe Problem gestoßen und habe die Entwicklung eines Plugins finanziert, das mir bei meiner Arbeit hilft. Ich habe das Plugin als Open Source veröffentlicht, damit auch andere davon profitieren können, und Sie können es auf Github herunterladen: https://github.com/eqcss/eqcss

Es gibt verschiedene Möglichkeiten, wie wir verschiedene Reaktionsstile anwenden können, je nachdem, was wir über ein Element auf der Seite wissen können. Hier sind einige Elementabfragen, mit denen Sie mit dem EQCSS-Plugin in CSS schreiben können:

@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 */
  }
}

Welche Bedingungen werden für reaktionsfähige Stile mit EQCSS unterstützt?

Gewichtsabfragen

  • min-width in px
  • min-width in %
  • max-width in px
  • max-width in %

Höhenabfragen

  • min-Höhe in px
  • min-Höhe in %
  • maximale Höhe in px
  • maximale Höhe in %

Abfragen zählen

  • Min-Zeichen
  • max-Zeichen
  • Min-Zeilen
  • maximale Anzahl an Zeilen
  • Min-Kinder
  • Max-Kinder

Spezielle Selektoren

In EQCSS-Elementabfragen können Sie auch drei spezielle Selektoren verwenden, mit denen Sie Ihre Stile genauer anwenden können:

  • $this (die Elemente, die der Abfrage entsprechen)
  • $parent (die übergeordneten Elemente der Elemente, die der Abfrage entsprechen)
  • $root(das Stammelement des Dokuments <html>)

Mit Elementabfragen können Sie Ihr Layout aus individuell ansprechenden Designmodulen zusammenstellen, die jeweils ein wenig "Selbstbewusstsein" dafür haben, wie sie auf der Seite angezeigt werden.

Mit EQCSS können Sie ein Widget so gestalten, dass es von 150 Pixel Breite bis 1000 Pixel Breite gut aussieht. Anschließend können Sie dieses Widget mithilfe einer beliebigen Vorlage (auf einer beliebigen Site) und in jeder Seitenleiste auf jeder Seite sicher ablegen

innovati
quelle
1
Schönes Projekt! Ich habe mir angesehen, was du gemacht hast
Yazz.com
@innovati Ich habe diesen Beitrag gefunden, als ich nach einer Möglichkeit gesucht habe, Abfragen zu Elementen durchzuführen. Ich kann es nicht zum Laufen bringen. Würde es Ihnen etwas ausmachen, mein Ticket anzusehen? github.com/eqcss/eqcss/issues/96
Andrew Newby
10

Aus Layoutsicht ist es möglich, moderne Techniken einzusetzen.

Es wurde (glaube ich) von Heydon Pickering erfunden. Er beschreibt den Prozess hier detailliert: http://www.heydonworks.com/article/the-flexbox-holy-albatross

Chris Coyier nimmt es auf und arbeitet hier eine Demo durch: https://css-tricks.com/putting-the-flexbox-albatross-to-real-use/

Um das Problem zu bekräftigen, unterhalb wir 3 derselben Komponente zu sehen, die jeweils aus drei orange divs markiert a, bund c.

Die Blöcke der zweiten beiden werden vertikal angezeigt, da sie auf den horizontalen Raum beschränkt sind, während die Blöcke der oberen Komponenten 3 horizontal angeordnet sind.

Es verwendet die flex-basisCSS-Eigenschaft und CSS-Variablen, um diesen Effekt zu erstellen.

Letztes Beispiel

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

Demo

Heydons Artikel besteht aus 1000 Wörtern, die ihn ausführlich erklären, und ich würde es wärmstens empfehlen, ihn zu lesen.

Djave
quelle
Das Ding aus Heydons Artikel ... Sieht aus und wirkt wie Magie! Vielen Dank für Ihre Antwort, ist super.
Ptyskju
2
Dies ist die Antwort, nach der jeder sucht, der über diese Frage stolpert
TehShrike
7

Die Frage ist sehr vage. Wie BoltClock sagt, kennen Medienabfragen nur die Abmessungen des Geräts. Sie können jedoch Medienabfragen in Kombination mit Abstiegsselektoren verwenden, um Anpassungen vorzunehmen.

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

Die einzige andere Lösung erfordert JS.

Cimmanon
quelle
47
Die Frage ist überhaupt nicht vage. In der Tat ist es eine sehr gute Frage. Leider gibt es keine gute Antwort darauf.
Stepanian
2
Schreckliche Wartung mit diesem Ansatz.
Totty.js
4

Ich kann mir nur vorstellen, dass Sie mit CSS das erreichen können, was Sie wollen, indem Sie einen Flüssigkeitsbehälter für Ihr Widget verwenden. Wenn die Breite Ihres Containers ein Prozentsatz des Bildschirms ist, können Sie Medienabfragen verwenden, um abhängig von der Breite Ihres Containers zu formatieren, da Sie jetzt für die Abmessungen jedes Bildschirms wissen, wie groß Ihr Container ist. Angenommen, Sie möchten, dass Ihr Container 50% der Bildschirmbreite ausmacht. Bei einer Bildschirmbreite von 1200 Pixel wissen Sie dann, dass Ihr Container 600 Pixel groß ist

.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
quelle
Nein, auf einem Bildschirm sieht es hässlich aus. Die Bildschirmgröße ändert sich schneller, aber das Element wird später und kleiner auf einem Bildschirm angezeigt.
Grün
3

Ich habe auch an Medienanfragen gedacht, aber dann habe ich Folgendes gefunden:

Erstellen Sie einfach einen Wrapper <div>mit einem Prozentwert für padding-bottom:

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

Es wird zu einem führen <div> Höhe von 75% der Breite des Behälters (ein Seitenverhältnis von 4: 3).

Diese Technik kann auch mit Medienabfragen und ein wenig Ad-hoc-Wissen über das Seitenlayout kombiniert werden, um eine noch feinere Steuerung zu erzielen.

Es ist genug für meine Bedürfnisse. Welches könnte auch für Ihre Bedürfnisse genug sein.

Hendy Irawan
quelle
2

Sie können den ResizeObserver verwenden API verwenden. Es ist noch in den Anfängen, daher wird es noch nicht von allen Browsern unterstützt (aber es gibt mehrere Polyfills, die Ihnen dabei helfen können).

Grundsätzlich können Sie mit dieser API einen Ereignis-Listener an die Größenänderung eines DOM-Elements anhängen.

Demo 1 - Demo 2

José Salgado
quelle
Für den Entwurf der Spezifikation gibt es eine Polyfüllung. github.com/juggle/resize-observer
Trevor Karjanis
Heydons Artikel bietet eine beispielhafte Implementierung dafür. Suchen Sie nach "ResizeObserver" auf der Seite: heydonworks.com/article/the-flexbox-holy-albatross
Gabe Rogan
0

Bei mir habe ich die maximale Breite des Div festgelegt, daher wird das kleine Widget nicht beeinflusst und die Größe des großen Widgets wird aufgrund des Stils mit maximaler Breite geändert.

  // assuming your widget class is "widget"
  .widget {
    max-width: 100%;
    height: auto;
  }
Jacky Choo
quelle
In der Frage wurde erwähnt, dass die Widget-Größe variieren kann. Durch Festlegen der maximalen Breite wird die Größe des Widgets nicht geändert, wenn der Container breit ist. .widgetist nur ein Beispiel als Klasse für das div des Widgets.
Jacky Choo