Могут ли медиазапросы изменять размер на основе элемента div вместо экрана?

317

Я хотел бы использовать медиа-запросы для изменения размера элементов в зависимости от размера divэлемента, в котором они находятся. Я не могу использовать размер экрана, поскольку divон используется просто как виджет на веб-странице, и его размер может варьироваться.

Обновить

Похоже, что над этим сейчас ведется работа: https://github.com/ResponsiveImagesCG/cq-demos

Yazz.com
источник
2
Я думаю, что этот вопрос слишком короткий, чтобы получить хороший ответ. Возможно, вы могли бы привести пример того, что вы пытаетесь сделать? Может быть, использовать jsfiddle.net, чтобы проверить свою идею и позволить другим помочь вам? Как правило, не должно быть никаких причин для того, что вы спрашиваете, вы должны быть в состоянии достичь желаемых результатов с помощью CSS без медиа-запросов. Вы можете использовать процентные размеры и ems для шрифтов, чтобы масштабировать вложенные элементы. Но, может быть, мне просто нужно увидеть пример вашего HTML-кода и CSS, чтобы лучше понять?
Бен Суэйн
1
Как может варьироваться размер вашего виджета? Ваша страница имеет фиксированную ширину (например, 960px) с областями просмотра выше 1024px или обе являются текучими? Это неясно и было бы полезно знать
FelipeAls
3
На самом деле, мой текущий проект имеет похожую ситуацию. Список элементов отображается в 2-цветном макете для широких устройств или в 1-столбном макете для узких устройств, но один элемент будет в 1-цветном макете, несмотря ни на что. И в списке, и в единственной версии есть 2 достаточно широких и коротких элемента. На более широких устройствах 2 элемента выглядят лучше всего бок о бок. В идеале узкие устройства: всегда вертикальные, широкие устройства: всегда параллельные, где-то между (в зависимости от 1 или 2-х столбцов): вертикальные или параллельные. Плавающее является простым решением, но ширина должна меняться в зависимости от макета.
Цимманон
1
LESS будет скомпилирован в CSS, поэтому, если CSS не поддерживает его, LESS также не сможет вам помочь.
jvannistelrooy
3
Ссылка больше не активна?
mix3d

Ответы:

228

Нет, медиазапросы не предназначены для работы на основе элементов на странице. Они предназначены для работы на основе устройств или типов носителей ( и, следовательно , почему они называются медиа - запросы). width, height, И другие средства измерения на основе имеет все относятся к размерам либо видового экрана или экрана устройства в экране на основе средств массовой информации. Их нельзя использовать для ссылки на определенный элемент на странице.

Если вам нужно применять стили в зависимости от размера определенного divэлемента на вашей странице, вам придется использовать JavaScript, чтобы наблюдать изменения в размере этого divэлемента вместо медиа-запросов.

BoltClock
источник
Я слышал о том, как я могу использовать функции с медиа-запросами, чтобы получить размер из содержащего элемента. Можно ли как-то совместить это с медиа-запросами для изменения размера элементов?
Yazz.com
1
Вы должны будете использовать JS, чтобы периодически получать ширину вашего элемента и реагировать соответствующим образом (периодически = каждую секунду или около того, или это замедлит работу некоторых браузеров; соответственно = переключением стилей для вашего виджета, если вы хотите самый быстрый метод).
FelipeAls
6
Чтобы сделать это изначально, нам нужны @elementзапросы. В W3C есть хорошая документация о рифме / причине @mediaзапросов: w3.org/TR/css3-mediaqueries/#width (по этой ссылке вы переходите к разделу, в котором обсуждаются widths - width типа media, а не элементы, содержащиеся в нем)
Доусон
Есть ли шанс заставить его работать в электронной почте? Я пытаюсь применить мобильный стиль к электронным письмам, когда контейнерный элемент div слишком мал (т. Е. Когда пространство электронной почты для настольной версии Gmail слишком мало, чтобы соответствовать дизайну с двумя столбцами, например, из-за изменения размера окна).
Лев
Кстати, запросы @element сделали бы css языком Тьюринга полным
Ник
117

Я только что создал javascript shim для достижения этой цели. Посмотрите, если хотите, это подтверждение концепции, но будьте осторожны: это ранняя версия, и она все еще нуждается в доработке.

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

Марк Дж. Шмидт
источник
5
Спасибо, я впечатлен
Yazz.com
5
Это невероятно. В сочетании с отзывчивым бутстрапом я делаю несколько потрясающих вещей, которых невозможно достичь просто с помощью @media. Отлично сработано.
Аку
3
Вы спасли наши жизни
Брода Ноэль
Ничего себе, действительно приятно, делает вещи намного проще
Кайзер
Прохладно. Есть вопрос. Как этот плагин определяет - какие элементы нужно min-widthобновить атрибуту; мне нужно вручную написать список css-класса, отмеченные элементы, включенные для min-widthобновления?
Александр Гончаров
38

Медиа-запрос внутри iframe может функционировать как запрос элемента. Я успешно реализовал это. Идея пришла из недавнего поста об Адаптивной рекламе от Zurb. Нет Javascript!

haddnin
источник
я думаю, что это лучшее решение, потому что медиа-запросы работают внутри iframe.
Эмфи
25

В настоящее время это невозможно только с помощью CSS, как @BoltClock написал в принятом ответе, но вы можете обойти это, используя JavaScript.

Я создал запрос контейнера (aka element query) prolyfill, чтобы решить эту проблему. Он работает немного иначе, чем другие скрипты, поэтому вам не нужно редактировать HTML-код ваших элементов. Все, что вам нужно сделать, это включить скрипт и использовать его в вашем CSS следующим образом:

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

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

ausi
источник
2
Это полно JS. Цель состоит в том, чтобы иметь функциональность только в CSS.
Грин
13
Prolyfillspolyfills ) обычно пишутся на JS, чтобы включить функцию, которая еще не поддерживается браузером. Цель prolyfill - стать устаревшей, как только эта функция поддерживается в CSS.
августа
3
@ius в этом вопросе не упоминается «только CSS». Как вы пришли к такому выводу?
ausi
1
@ius за исключением того, что вы не можете сделать это в CSS, поэтому предложение решения вне CSS вполне разумно. Гораздо лучше, чем «нет, ты не можешь», ты так не думаешь;)
Уэсли Смит
1
@ DelightedD0D после моего комментария он изменил ответ, и я проголосовал +1 за изменение. Текущий ответ мне подходит, потому что говорит, что это невозможно только с помощью CSS.
МСС
17

Я столкнулся с той же проблемой пару лет назад и финансировал разработку плагина, чтобы помочь мне в моей работе. Я выпустил плагин с открытым исходным кодом, чтобы другие тоже могли его использовать, и вы можете скачать его на Github: https://github.com/eqcss/eqcss

Существует несколько способов применения различных адаптивных стилей в зависимости от того, что мы можем знать об элементе на странице. Вот несколько запросов к элементам, которые плагин EQCSS позволит вам написать в 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 */
  }
}

Итак, какие условия поддерживаются для адаптивных стилей с EQCSS?

Весовые Запросы

  • минимальная ширина в px
  • минимальная ширина в %
  • максимальная ширина в px
  • максимальная ширина в %

Высота запросов

  • минимальная высота в px
  • минимальная высота в %
  • максимальная высота в px
  • максимальная высота в %

Количество запросов

  • мин-символы
  • макс-символы
  • мин-линии
  • макс-линия
  • мин-дети
  • Макс-дети

Специальные селекторы

В запросах элементов EQCSS вы также можете использовать три специальных селектора, которые позволяют более конкретно применять ваши стили:

  • $this (элемент (ы), соответствующий запросу)
  • $parent (родительский элемент (ы) элемента (ов), соответствующего запросу)
  • $root(корневой элемент документа, <html>)

Запросы элементов позволяют вам составить свой макет из индивидуально реагирующих дизайнерских модулей, каждый из которых имеет немного «самосознания» о том, как они отображаются на странице.

С помощью EQCSS вы можете создать один виджет, который будет хорошо выглядеть от ширины 150 пикселей до ширины до 1000 пикселей, а затем вы можете уверенно поместить этот виджет в любую боковую панель на любой странице, используя любой шаблон (на любом сайте), и

инноваци
источник
1
Хороший проект! Я посмотрел на то, что вы сделали
Yazz.com
@innovati Я нашел этот пост, когда искал способ выполнять запросы к элементам. Я не могу заставить его работать. Не могли бы вы посмотреть на мой билет? github.com/eqcss/eqcss/issues/96
Эндрю Ньюби
10

С точки зрения макета, это возможно с использованием современных методов.

Это сделано (я полагаю) Хейдоном Пикерингом. Он детализирует процесс здесь: http://www.heydonworks.com/article/the-flexbox-holy-albatross

Крис Койер поднимает его и работает с демонстрацией здесь: https://css-tricks.com/putting-the-flexbox-albatross-to-real-use/

Чтобы повторить проблему, ниже мы видим 3 одинаковых компонента, каждый из которых состоит из трех оранжевых элементов с метками a, bи c.

Блоки вторых двух отображаются вертикально, потому что они ограничены горизонтальным пространством, тогда как верхние компоненты 3 блока расположены горизонтально.

flex-basisДля создания этого эффекта используются свойство CSS и переменные CSS.

Последний пример

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

демонстрация

Статья Хейдона состоит из 1000 слов, подробно объясняющих ее, и я очень рекомендую ее прочитать.

Djave
источник
Эта вещь из статьи Хейдона ... Выглядит и работает как волшебство! Спасибо за ваш ответ, это здорово.
Птыскую
2
Это ответ, который ищут все спотыкающиеся в этом вопросе
TehShrike
7

Вопрос очень расплывчатый. Как говорит BoltClock, медиазапросы знают только размеры устройства. Однако вы можете использовать медиазапросы в сочетании с селекторами по убыванию для выполнения настроек.

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

Единственное другое решение требует JS.

cimmanon
источник
47
Вопрос совсем не расплывчатый. На самом деле это очень хороший вопрос. К сожалению, нет хорошего ответа на это.
Степанян
2
Ужасное обслуживание с использованием этого подхода.
Totty.js
4

Единственный способ, которым я могу думать, что вы можете выполнить то, что вы хотите чисто с помощью CSS, - это использовать контейнер для жидкости для вашего виджета. Если ширина вашего контейнера составляет процент от экрана, вы можете использовать медиазапросы для стилизации в зависимости от ширины вашего контейнера, так как теперь вы будете знать для каждого размера экрана, каковы размеры вашего контейнера. Например, допустим, вы решили сделать свой контейнер 50% ширины экрана. Тогда для ширины экрана 1200 пикселей вы знаете, что ваш контейнер составляет 600 пикселей

.myContainer {
  width: 50%;
}

/* you know know that your container is 600px 
 * so you style accordingly
*/
@media (max-width: 1200px) { 
  /* your css for 600px container */
}
Румелис Джордж
источник
Нет, на экране это выглядит ужасно. Размер экрана меняется быстрее, но элемент появляется на экране позже и меньше.
Грин
3

Я также думал о медиа-запросах, но потом я нашел это:

Просто создайте оболочку <div>с процентным значением для padding-bottom, например так:

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

В результате получится <div>высота, равная 75% ширины контейнера (соотношение сторон 4: 3).

Этот метод также может сочетаться с медиа-запросами и некоторыми специальными знаниями о макете страницы для еще более детального контроля.

Этого достаточно для моих нужд. Что может быть достаточно для ваших нужд.

Хенди ираван
источник
2

Вы можете использовать ResizeObserver API. Это все еще в первые дни, так что он еще не поддерживается всеми браузерами (но есть несколько полифилов, которые могут помочь вам в этом).

По сути, этот API позволяет вам присоединить прослушиватель событий к изменению размера элемента DOM.

Демо 1 - Демо 2

Хосе Сальгадо
источник
Для проекта спецификации есть полифилл. github.com/juggle/resize-observer
Тревор Карджанис,
Статья Хейдона предоставляет пример реализации этого. Поиск "ResizeObserver" на странице: heydonworks.com/article/the-flexbox-holy-albatross
Гейб Роган
0

Для моего я сделал это, установив максимальную ширину div, следовательно, для маленького виджета это не будет затронуто, а большой виджет будет изменен из-за стиля max-width.

  // assuming your widget class is "widget"
  .widget {
    max-width: 100%;
    height: auto;
  }
Джеки Чу
источник
В вопросе упоминалось, что размер виджета может варьироваться, установка max-width не изменит размер виджета, когда контейнер широкий. .widgetэто просто образец в качестве класса для div виджета.
Джеки Чу