Les requêtes multimédias peuvent-elles être redimensionnées en fonction d'un élément div au lieu de l'écran?

317

Je voudrais utiliser des requêtes multimédias pour redimensionner des éléments en fonction de la taille d'un divélément dans lequel ils se trouvent. Je ne peux pas utiliser la taille de l'écran car il divest simplement utilisé comme un widget dans la page Web, et sa taille peut varier.

Mettre à jour

Il semble que des travaux soient en cours à ce sujet: https://github.com/ResponsiveImagesCG/cq-demos

Yazz.com
la source
2
Je pense que cette question est trop brève pour obtenir une bonne réponse. Peut-être pourriez-vous donner un exemple de ce que vous essayez de faire? Utilisez peut-être jsfiddle.net pour tester votre idée et permettre à d'autres de vous aider? Généralement, il ne devrait y avoir aucune raison à ce que vous demandez, vous devriez être en mesure d'obtenir les résultats souhaités avec CSS sans requêtes de médias. Vous pouvez utiliser des dimensions en pourcentage et des em pour les polices pour mettre à l'échelle les éléments imbriqués. Mais peut-être que j'ai juste besoin de voir un exemple de votre code html et css pour mieux comprendre?
BenSwayne
1
Comment la taille de votre widget peut-elle varier? La largeur de votre page est-elle fixe (960 px par exemple) avec des fenêtres supérieures à 1024 px ou les deux sont-elles fluides? Ce n'est pas clair et il serait utile de le savoir
FelipeAls
3
En fait, mon projet actuel a une situation similaire. Une liste d'éléments est affichée dans une disposition 2 couleurs pour les appareils larges ou 1 couleur pour les appareils étroits, mais un seul élément sera dans une disposition 1 couleur quoi qu'il arrive. La liste et la version unique ont toutes deux deux éléments assez larges et courts. Sur les appareils plus larges, les 2 éléments sont les meilleurs côte à côte. Idéalement, appareils étroits: toujours verticaux, appareils larges: toujours parallèles, quelque part entre (selon 1 ou 2 cols): verticaux ou parallèles. Le flottement est la solution simple, mais la largeur doit également varier en fonction de la disposition.
cimmanon
1
LESS sera compilé en CSS, donc si CSS ne le prend pas en charge, LESS ne peut pas non plus vous aider.
jvannistelrooy
3
Le lien n'est plus actif?
mix3d

Réponses:

228

Non, les requêtes multimédias ne sont pas conçues pour fonctionner en fonction des éléments d'une page. Ils sont conçus pour fonctionner en fonction des appareils ou des types de supports (d'où leur raison d'être des requêtes de supports ). width,, heightet d'autres fonctionnalités multimédias basées sur des dimensions font toutes référence aux dimensions de la fenêtre ou de l'écran du périphérique dans les médias basés sur l'écran. Ils ne peuvent pas être utilisés pour faire référence à un certain élément sur une page.

Si vous devez appliquer des styles en fonction de la taille d'un certain divélément de votre page, vous devrez utiliser JavaScript pour observer les changements de taille de cet divélément au lieu des requêtes multimédias.

BoltClock
la source
J'ai entendu parler d'un moyen d'utiliser des fonctions avec des requêtes multimédias pour obtenir la taille d'un élément conteneur. Existe-t-il un moyen de combiner cela avec des requêtes de médias pour redimensionner des éléments?
Yazz.com
1
Vous devez utiliser JS pour obtenir périodiquement la largeur de votre élément et réagir en conséquence (périodiquement = toutes les secondes environ ou cela ralentira certains navigateurs; en conséquence = en basculant les classes en stylisant votre widget si vous voulez la méthode la plus rapide).
FelipeAls
6
Pour accomplir cela nativement, nous aurions besoin de @elementrequêtes. Le W3C a une bonne documentation sur la rime / la raison des @mediarequêtes: w3.org/TR/css3-mediaqueries/#width (ce lien vous amène à la section discutant des largeurs --- largeurs du type de média, pas les éléments contenus dans)
Dawson
Avez-vous une chance de le faire fonctionner dans les e-mails? J'essaie d'appliquer un style mobile aux e-mails lorsque la division du conteneur est trop petite (c'est-à-dire lorsque l'espace de messagerie de la version de bureau Gmail est trop petit pour s'adapter à une conception à 2 colonnes, en raison du redimensionnement de la fenêtre par exemple).
Lev
Soit dit en passant, les requêtes @element feraient de CSS un langage complet de Turing
Nick
117

Je viens de créer un shim javascript pour atteindre cet objectif. Jetez un coup d'œil si vous le souhaitez, c'est une preuve de concept, mais attention: c'est une version ancienne et a encore besoin de travail.

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

Marc J. Schmidt
la source
5
Merci, je suis impressionné
Yazz.com
5
C'est incroyable. Combiné avec un bootstrap réactif, je fais des choses impressionnantes qui ne pourraient pas être réalisées avec seulement @media. Bien joué.
Aku
3
Vous nous avez sauvé la vie
Broda Noel
Wow, vraiment sympa, rend les choses beaucoup plus faciles
kaiser
Cool. Ayez la question. Maintenant, ce plugin détecte - quels éléments doivent être min-widthrenouvelés; dois-je écrire manuellement la liste de classe css, les éléments marqués, activés pour le min-widthrenouvellement?
Alexander Goncharov
38

Une requête multimédia à l'intérieur d'une iframe peut fonctionner comme une requête d'élément. J'ai réussi à implémenter cela. L'idée est venue d'un récent article sur les annonces responsives de Zurb. Pas de Javascript!

haddnin
la source
Je pense que c'est la meilleure solution, car les requêtes média fonctionnent dans l'iframe.
emfi
25

Ce n'est actuellement pas possible avec CSS seul comme l'écrit @BoltClock dans la réponse acceptée, mais vous pouvez contourner cela en utilisant JavaScript.

J'ai créé un prolyfill de requête de conteneur (aka requête d'élément) pour résoudre ce type de problème. Il fonctionne un peu différemment des autres scripts, vous n'avez donc pas à modifier le code HTML de vos éléments. Tout ce que vous avez à faire est d'inclure le script et de l'utiliser comme ceci dans votre CSS:

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

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

ausi
la source
2
Il est plein de JS. Le but est d'avoir la fonctionnalité en CSS uniquement.
Green
13
Les Prolyfills (et polyfills ) sont généralement écrits en JS pour activer une fonctionnalité qui n'est pas encore prise en charge par le navigateur. Le but du prolyfill est de devenir obsolète une fois que cette fonctionnalité est prise en charge en CSS.
ausi
3
@ius il n'y a aucune mention de «CSS uniquement» dans la question. Comment êtes-vous arriver à cette conclusion?
ausi
1
@ius sauf que vous ne pouvez pas le faire en CSS, donc proposer une solution en dehors de CSS est parfaitement raisonnable. Beaucoup mieux que "non tu ne peux pas" ne pensez-vous pas;)
Wesley Smith
1
@ DelightedD0D après mon commentaire, il a changé la réponse et j'ai voté +1 pour le changement. La réponse actuelle est OK pour moi car elle dit que ce n'est pas possible avec CSS uniquement.
ius
17

J'ai rencontré le même problème il y a quelques années et j'ai financé le développement d'un plugin pour m'aider dans mon travail. J'ai publié le plugin en open-source pour que d'autres puissent en bénéficier également, et vous pouvez le récupérer sur Github: https://github.com/eqcss/eqcss

Il existe plusieurs façons d'appliquer différents styles réactifs en fonction de ce que nous pouvons savoir sur un élément de la page. Voici quelques requêtes d'éléments que le plugin EQCSS vous permettra d'écrire en 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 */
  }
}

Quelles sont donc les conditions prises en charge pour les styles réactifs avec EQCSS?

Requêtes de poids

  • largeur min en px
  • largeur min en %
  • largeur max en px
  • largeur max en %

Requêtes de hauteur

  • min-hauteur en px
  • min-hauteur en %
  • hauteur max en px
  • hauteur max en %

Nombre de requêtes

  • min-caractères
  • max-caractères
  • min-lignes
  • max-lines
  • min-enfants
  • max-enfants

Sélecteurs spéciaux

Dans les requêtes d'éléments EQCSS, vous pouvez également utiliser trois sélecteurs spéciaux qui vous permettent d'appliquer plus spécifiquement vos styles:

  • $this (le ou les éléments correspondant à la requête)
  • $parent (les éléments parents des éléments correspondant à la requête)
  • $root(l'élément racine du document, <html>)

Les requêtes d'éléments vous permettent de composer votre mise en page à partir de modules de conception adaptés individuellement, chacun avec un peu de «conscience de soi» de la façon dont ils sont affichés sur la page.

Avec EQCSS, vous pouvez concevoir un widget pour qu'il soit beau de 150 pixels de large jusqu'à 1000 pixels de large, puis vous pouvez déposer ce widget en toute confiance dans n'importe quelle barre latérale de n'importe quelle page en utilisant n'importe quel modèle (sur n'importe quel site) et

innovati
la source
1
Beau projet! J'ai regardé ce que vous avez fait
Yazz.com
@innovati J'ai trouvé ce message en cherchant un moyen de faire des requêtes sur les éléments. Je n'arrive pas à le faire fonctionner. Pourriez-vous regarder mon billet? github.com/eqcss/eqcss/issues/96
Andrew Newby
10

Du point de vue de la mise en page, il est possible d'utiliser des techniques modernes.

Son composé (je crois) par Heydon Pickering. Il détaille le processus ici: http://www.heydonworks.com/article/the-flexbox-holy-albatross

Chris Coyier le récupère et travaille à travers une démonstration ici: https://css-tricks.com/putting-the-flexbox-albatross-to-real-use/

Pour reformuler le problème, nous voyons ci-dessous 3 du même composant, chacun composé de trois divs orange étiquetés a, bet c.

Les blocs des deux derniers s'affichent verticalement, car ils sont limités sur la pièce horizontale, tandis que les composants supérieurs 3 blocs sont disposés horizontalement.

Il utilise la flex-basispropriété CSS et les variables CSS pour créer cet effet.

Dernier exemple

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

Démo

L'article de Heydon est de 1000 mots l'expliquant en détail, et je recommande fortement de le lire.

Djave
la source
Cette chose de l'article de Heydon ... ressemble et fonctionne comme par magie! Merci pour votre réponse, c'est génial.
ptyskju
2
C'est la réponse que tout le monde butant sur cette question cherche
TehShrike
7

La question est très vague. Comme le dit BoltClock, les requêtes multimédias ne connaissent que les dimensions de l'appareil. Cependant, vous pouvez utiliser des requêtes multimédias en combinaison avec des sélecteurs de descendant pour effectuer des ajustements.

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

La seule autre solution nécessite JS.

cimmanon
la source
47
La question n'est pas du tout vague. En fait, c'est une très bonne question. Malheureusement, il n'y a pas de bonne réponse.
stepanian
2
Maintenance horrible en utilisant cette approche.
Totty.js
4

La seule façon dont je peux penser que vous pouvez accomplir ce que vous voulez uniquement avec CSS, est d'utiliser un conteneur fluide pour votre widget. Si la largeur de votre conteneur est un pourcentage de l'écran, vous pouvez utiliser des requêtes multimédias pour styliser en fonction de la largeur de votre conteneur, car vous saurez maintenant pour les dimensions de chaque écran quelles sont les dimensions de votre conteneur. Par exemple, supposons que vous décidiez de faire de votre conteneur 50% de la largeur de l'écran. Alors pour une largeur d'écran de 1200px vous savez que votre container fait 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
la source
Non, ça a l'air moche sur un écran. La taille de l'écran change plus rapidement, mais l'élément apparaît sur un écran plus tard et plus petit.
Green
3

Je pensais également aux requêtes des médias, mais j'ai trouvé ceci:

Créez simplement un wrapper <div>avec un pourcentage pour padding-bottom, comme ceci:

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

Il en résultera une <div>hauteur égale à 75% de la largeur de son contenant (un rapport d'aspect de 4: 3).

Cette technique peut également être associée à des requêtes multimédias et à un peu de connaissances ad hoc sur la mise en page pour un contrôle encore plus fin.

C'est suffisant pour mes besoins. Ce qui pourrait aussi suffire à vos besoins.

Hendy Irawan
la source
2

Vous pouvez utiliser le ResizeObserver API . C'est encore à ses débuts, il n'est pas encore pris en charge par tous les navigateurs (mais il existe plusieurs polyfills qui peuvent vous aider avec cela).

Fondamentalement, cette API vous permet d'attacher un écouteur d'événements au redimensionnement d'un élément DOM.

Démo 1 - Démo 2

José Salgado
la source
Il existe un polyfill pour le projet de spécification. github.com/juggle/resize-observer
Trevor Karjanis
L'article de Heydon fournit un exemple d'implémentation de ceci. Rechercher "ResizeObserver" sur la page: heydonworks.com/article/the-flexbox-holy-albatross
Gabe Rogan
0

Pour le mien, je l'ai fait en définissant la largeur maximale de la div, donc pour le petit widget ne sera pas affecté et le grand widget est redimensionné en raison du style max-width.

  // assuming your widget class is "widget"
  .widget {
    max-width: 100%;
    height: auto;
  }
Jacky Choo
la source
La question mentionne que la taille du widget peut varier, la définition de max-width ne changera pas la taille du widget lorsque le conteneur est large. .widgetest juste un échantillon comme classe pour la div du widget.
Jacky Choo