As consultas de mídia podem ser redimensionadas com base em um elemento div em vez da tela?


317

Eu gostaria de usar consultas de mídia para redimensionar elementos com base no tamanho de um divelemento em que estão. Não posso usar o tamanho da tela, pois ele divé usado apenas como um widget na página da Web, e seu tamanho pode variar.

Atualizar

Parece que há trabalho sendo feito sobre isso agora: https://github.com/ResponsiveImagesCG/cq-demos


2
Penso que esta pergunta é breve demais para obter uma boa resposta. Talvez você possa fornecer um exemplo do que você está tentando fazer? Talvez use jsfiddle.net para testar sua ideia e permitir que outras pessoas o ajudem? Geralmente, não deve haver razão para o que você está perguntando; você deve conseguir os resultados desejados com CSS sem consultas de mídia. Você pode usar dimensões percentuais e ems para fontes para dimensionar elementos aninhados. Mas talvez eu só precise ver um exemplo do seu código html e css para entender melhor?
BenSwayne

1
Como o tamanho do seu widget pode variar? Sua página possui largura fixa (960 px por exemplo) com viewports acima de 1024 px ou ambas são fluidas? Isso é claro e seria útil saber
FelipeAls

3
Na verdade, meu projeto atual tem uma situação semelhante. Uma lista de itens é exibida em um layout de 2 colunas para dispositivos amplos ou layout de 1 coluna para dispositivos estreitos, mas um único item estará em um layout de 1 coluna, não importa o quê. Tanto a lista quanto a versão única possuem 2 elementos bastante amplos e curtos. Em dispositivos mais amplos, os 2 elementos ficam melhor lado a lado. Idealmente, dispositivos estreitos: sempre verticais, dispositivos largos: sempre paralelos, em algum lugar entre (dependendo de 1 ou 2-col): vertical ou paralelo. Flutuar é a solução simples, mas a largura precisa variar também, dependendo do layout.
Cimmanon 09/09/12

1
LESS será compilado para CSS, portanto, se o CSS não o suportar, LESS também não poderá ajudá-lo.
jvannistelrooy

3
O link não está mais ativo?
mix3d

Respostas:


228

Não, as consultas de mídia não foram projetadas para funcionar com base nos elementos de uma página. Eles são projetados para funcionar com base em dispositivos ou tipos de mídia (por isso são chamados de consultas de mídia ). width,, heighte outros recursos de mídia baseados em dimensões referem-se às dimensões da janela de exibição ou da tela do dispositivo na mídia baseada em tela. Eles não podem ser usados ​​para se referir a um determinado elemento em uma página.

Se você precisar aplicar estilos, dependendo do tamanho de um determinado divelemento da sua página, precisará usar JavaScript para observar alterações no tamanho desse divelemento, em vez de consultas de mídia.


Ouvi falar de alguma maneira de poder usar funções com consultas de mídia para obter o tamanho de um elemento que contém. Existe alguma maneira de combinar isso com consultas de mídia para redimensionar elementos?
Yazz.com

1
Você precisaria usar o JS para obter periodicamente a largura do seu elemento e reagir de acordo (periodicamente = a cada segundo ou mais ou menos, isso desacelerará alguns navegadores; consequentemente = alternando as classes que denominam o widget, se você quiser o método mais rápido).
FelipeAls

6
Para fazer isso de forma nativa, precisaríamos de @elementconsultas. O W3C possui uma boa documentação sobre a rima / motivo das @mediaconsultas: w3.org/TR/css3-mediaqueries/#width (este link leva você à seção discutindo larguras --- larguras do tipo de mídia, e não os elementos contidos nela)
Dawson

Alguma chance de fazê-lo funcionar em e-mails? Estou tentando aplicar estilo móvel a emails quando a div do contêiner é muito pequena (por exemplo, quando o espaço de email da versão da área de trabalho do Gmail é muito pequeno para se ajustar ao design de duas colunas, devido ao redimensionamento da janela, por exemplo).
Lev

By the way, consultas @element faria css uma linguagem completa Turing
Nick

117

Acabei de criar um calço javascript para atingir esse objetivo. Dê uma olhada, se quiser, é uma prova de conceito, mas tome cuidado: é uma versão inicial e ainda precisa de algum trabalho.

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


5
Obrigado, estou impressionado
Yazz.com 4/13

5
Isto é incrível. Combinado com o bootstrap responsivo, estou fazendo coisas incríveis que não poderiam ser alcançadas apenas com o @media. Bem feito.
Aku

3
Você salvou nossas vidas
Broda Noel

Uau, muito bom, torna as coisas muito mais fácil
kaiser

Legal. Tenha a pergunta. Н Como detectar este plugin - quais elementos precisam ser min-widthrenovados; preciso escrever manualmente a lista de classes css, elementos marcados, ativados para min-widthrenovação?
Alexander Goncharov

38

Uma Consulta de Mídia dentro de um iframe pode funcionar como uma consulta de elemento. Eu implementei isso com sucesso. A ideia surgiu de um post recente sobre o Responsive Ads by Zurb. Sem Javascript!


Eu acho que essa é a melhor solução, porque as consultas de mídia funcionam dentro do iframe.
EMFI

25

No momento, isso não é possível apenas com CSS, como o @BoltClock escreveu na resposta aceita, mas você pode contornar isso usando JavaScript.

Criei um prolyfill de consulta de contêiner (também conhecido como consulta de elemento) para resolver esse tipo de problema. Funciona um pouco diferente de outros scripts, portanto você não precisa editar o código HTML dos seus elementos. Tudo o que você precisa fazer é incluir o script e usá-lo no seu CSS da seguinte maneira:

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

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


2
Está cheio de JS. O objetivo é ter a funcionalidade apenas em CSS.
Green

13
Prolyfills (e polyfills ) geralmente são escritos em JS para ativar um recurso que ainda não é suportado pelo navegador. O objetivo do prolyfill é tornar-se obsoleto quando esse recurso for suportado no CSS.
Ausi

3
@ius não há menção a "CSS only" na questão. Como você chegou a essa conclusão?
Ausi

1
@ius, exceto que você não pode fazê-lo em CSS, portanto, oferecer uma solução fora do CSS é perfeitamente razoável. Muito melhor do que "nenhum você não pode" você não acha;)
Wesley Smith

1
@ DelightedD0D depois do meu comentário, ele mudou a resposta e eu votei em +1 na mudança. A resposta atual é boa para mim, porque está dizendo que isso não é possível apenas com CSS.
ius 28/07

17

Encontrei o mesmo problema há alguns anos e financiei o desenvolvimento de um plugin para me ajudar no meu trabalho. Lancei o plug-in como código-fonte aberto para que outros possam se beneficiar dele, e você pode acessá-lo no Github: https://github.com/eqcss/eqcss

Existem algumas maneiras pelas quais podemos aplicar diferentes estilos responsivos com base no que podemos saber sobre um elemento na página. Aqui estão algumas consultas de elementos que o plug-in EQCSS permitirá que você escreva em 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 */
  }
}

Então, quais condições são suportadas para estilos responsivos com o EQCSS?

Consultas de peso

  • largura mínima em px
  • largura mínima em %
  • largura máxima em px
  • largura máxima em %

Consultas de altura

  • altura mínima em px
  • altura mínima em %
  • altura máxima em px
  • altura máxima em %

Contar consultas

  • caracteres mínimos
  • max-characters
  • linhas mínimas
  • max-lines
  • min-crianças
  • max-crianças

Seletores Especiais

Nas consultas do elemento EQCSS, você também pode usar três seletores especiais que permitem aplicar seus estilos mais especificamente:

  • $this (o (s) elemento (s) correspondente (s) à consulta)
  • $parent (o (s) elemento (s) pai (s) do (s) elemento (s) correspondente (s) à consulta)
  • $root(o elemento raiz do documento <html>)

As consultas de elemento permitem que você componha seu layout a partir de módulos de design responsivos individualmente, cada um com um pouco de 'autoconsciência' de como eles estão sendo exibidos na página.

Com o EQCSS, você pode criar um widget para ter uma boa aparência, de 150px a 1000px, e então soltar esse widget em qualquer barra lateral de qualquer página, usando qualquer modelo (em qualquer site) e


1
Bom projeto! Dei uma olhada no que você fez
Yazz.com 12/11/2015

@innovati Encontrei este post enquanto procurava uma maneira de fazer consultas sobre elementos. Não consigo fazê-lo funcionar. Você se importaria de olhar para o meu bilhete? github.com/eqcss/eqcss/issues/96
Andrew Newby

10

Do ponto de vista do layout, é possível usar técnicas modernas.

É composta (acredito) por Heydon Pickering. Ele detalha o processo aqui: http://www.heydonworks.com/article/the-flexbox-holy-albatross

Chris Coyier pega e trabalha através de uma demonstração aqui: https://css-tricks.com/putting-the-flexbox-albatross-to-real-use/

Para reafirmar a questão, abaixo, vemos 3 do mesmo componente, cada uma composta de três divs laranja rotulados a, be c.

Os blocos dos dois segundos são exibidos verticalmente, porque são limitados na sala horizontal, enquanto os três componentes principais são dispostos horizontalmente.

Ele usa a flex-basispropriedade CSS e variáveis ​​CSS para criar esse efeito.

Exemplo final

.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

O artigo de Heydon tem 1000 palavras, explicando-o em detalhes, e eu recomendo a leitura.


Essa coisa do artigo de Heydon ... Parece e funciona como mágica! Obrigado pela sua resposta, é incrível.
ptyskju 14/01

2
Esta é a resposta que todos tropeço sobre esta questão está procurando
TehShrike

7

A questão é muito vaga. Como o BoltClock diz, as consultas de mídia conhecem apenas as dimensões do dispositivo. No entanto, você pode usar consultas de mídia em combinação com seletores de descendente para realizar ajustes.

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

A única outra solução requer JS.


47
A questão não é vaga. De fato, é uma pergunta muito boa. Infelizmente, não há uma boa resposta para isso.
stepanian 16/08

2
Manutenção terrível usando essa abordagem.
Totty.js 03/12

4

A única maneira de pensar que você pode realizar o que deseja puramente com css é usar um contêiner de fluido para seu widget. Se a largura do contêiner for uma porcentagem da tela, você poderá usar consultas de mídia para estilizar, dependendo da largura do contêiner, pois agora você saberá para as dimensões de cada tela quais são as dimensões do contêiner. Por exemplo, digamos que você decida aumentar em 50% a largura da tela do seu contêiner. Para uma largura de tela de 1200 pixels, você sabe que seu contêiner tem 600 pixels

.myContainer {
  width: 50%;
}

/* you know know that your container is 600px 
 * so you style accordingly
*/
@media (max-width: 1200px) { 
  /* your css for 600px container */
}

Não, parece feio na tela. O tamanho da tela muda mais rapidamente, mas o elemento aparece em uma tela mais tarde e menor.
Green

3

Eu também estava pensando em consultas de mídia, mas descobri o seguinte:

Basta criar um wrapper <div>com um valor percentual para padding-bottom, assim:

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

Isso resultará em uma <div>altura igual a 75% da largura do seu contêiner (uma proporção de 4: 3).

Essa técnica também pode ser combinada com consultas de mídia e um pouco de conhecimento ad hoc sobre o layout da página para um controle ainda mais refinado.

É o suficiente para minhas necessidades. O que também pode ser suficiente para suas necessidades.


2

Você pode usar a API ResizeObserver . Ainda está nos primeiros dias, portanto ainda não é suportado por todos os navegadores (mas existem vários polyfills que podem ajudá-lo).

Basicamente, essa API permite anexar um ouvinte de evento ao redimensionamento de um elemento DOM.

Demo 1 - Demo 2


Há um polyfill para a especificação de rascunho. github.com/juggle/resize-observer
Trevor Karjanis em

O artigo de Heydon fornece um exemplo de implementação disso. Pesquise "ResizeObserver" na página: heydonworks.com/article/the-flexbox-holy-albatross
Gabe Rogan

0

Para o meu, eu fiz isso definindo a largura máxima da div, portanto, o widget pequeno não será afetado e o widget grande é redimensionado devido ao estilo de largura máxima.

  // assuming your widget class is "widget"
  .widget {
    max-width: 100%;
    height: auto;
  }

A pergunta mencionou que o tamanho do widget pode variar, a configuração de largura máxima não mudará o tamanho do widget quando o contêiner for largo. .widgeté apenas uma amostra como a classe para a div do widget.
Jacky Choo
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.