Использование блочной модели для размещения элементов в родительском div

Используя следующие правила HTML и CSS3, я пытаюсь убедиться, что соблюдены следующие критерии:

У меня работают все критерии, кроме пункта 1, где дети превышают ширину своего родителя. Вопрос: Как удержать детей внутри родителя?

  1. Элементы li не могут превышать ширину своего родителя, т. е. 400 пикселей.
  2. img, метка и содержимое валюты должны располагаться вертикально по центру в пределах их диапазона.
  3. валюта не должна переноситься и всегда должна отображаться полностью
  4. валюта всегда должна отображаться как можно ближе к диапазону метки.
  5. текст этикетки должен быть заключен в 2 строки с многоточием, отображаемым там, где он превышает 2 строки.

Примечание. Должен работать только в браузерах Chrome и Safari на базе webkit.

Это должно выглядеть так:

введите здесь описание изображения

Однако на данный момент это выглядит так:

введите здесь описание изображения

Любые идеи?

********************* JS Fiddle пример ***************************

<ul>
    <li>
        <span class="img"></span>
        <span class="label">Acclaim</span>
        <span class="currency">(USD 50)</span>
    </li>

    <li>
        <span class="img"></span>
        <span class="label">Acclaim 1 11 111 1111 11111</span>
        <span class="currency">(USD 50)</span>
    </li>

    <li>
        <span class="img"></span>
        <span class="label">Acclaim 1 11 111 1111 11111 2 22222 2222 22222 3 33 333 3333 33333 4 44 444 4444 44444 5 55 555 5555 55555 6 66 666 6666 66666</span>
        <span class="currency">(USD 50)</span>
   </li>
</ul>


ul {
    width: 400px;

    background-color: yellow;
    padding: 0;
    margin: 0;
}

li {
    display: -webkit-box;

    padding-right: 50px;
}

.label {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-box-pack: center;

    -webkit-line-clamp: 2;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: normal;
    word-wrap: break-word;
    line-height: 1.3em;
    margin-right: 0.2em;    

    background-color: pink;    
}

.currency {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-box-pack: center;

    white-space: nowrap;

    background-color: lightgreen;    
}

.img {
    display: block;
    width: 40px;
    height: 40px;
    margin-right: 0.1em;

    background-image:url('data:image/png;base64,iVBOR...);
}

person Philip Murphy    schedule 25.04.2013    source источник
comment
Вот еще одна скрипка, с которой я работаю с гибкой моделью, но только в Chrome. Это все еще не работает для Safari? jsfiddle.net/tUqvG - однако, как я могу, это что-то вроде сочетания гибких и блочных моделей. Заставьте многоточие и линейный зажим работать с гибкой моделью.   -  person Philip Murphy    schedule 25.04.2013
comment
Flexbox не заменил блочную модель. Это просто еще один вариант оформления.   -  person David Storey    schedule 17.05.2013
comment
Вы не получите line-clamp для работы с блочной моделью или гибкой моделью в Safari, поскольку text-overflow: многоточие не предназначено для многострочного текста, ваше просто удачное решение для Chrome. :) См. quirksmode.org/css/user-interface/textoverflow.html.   -  person Volker E.    schedule 18.05.2013
comment
Возможно, вы могли бы подделать text-overflow: многоточие с помощью селектора :after и content: '…', но в любом случае это будет не слишком приятно.   -  person Volker E.    schedule 18.05.2013
comment
@DavidStorey Удалил это утверждение как неверное.   -  person Philip Murphy    schedule 16.09.2013


Ответы (2)


Следующее будет работать, если цена не станет шире:

http://jsfiddle.net/WDjZ3/4/

Я просто преобразовал margin-right в пиксели, чтобы знать пространство, занимаемое содержимым, кроме метки, а затем добавил максимальную ширину для остатка:

.label {   
    margin-right: 3px;  
    max-width: 294px;
}

если цена или изображение имеют переменную ширину, вам понадобится js, чтобы прочитать их ширину, удалить из 400 пикселей и добавить это значение к максимальной ширине.

Вот пример использования JavaScript для динамической установки максимальной ширины: http://jsfiddle.net/WDjZ3/7/

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

Я в основном проверил ширину других элементов:

function getWidth(el) {   
    return parseInt(window.getComputedStyle(el,null).getPropertyValue("width"));
}

Затем я удалил эту ширину с 400 пикселей и установил maxWidth:

for (var i=0; i<imgs.length; i++) {
    var width = 400 - (getWidth(imgs[i]) + getWidth(currencies[i])) + "px"; 
    labels[i].style.maxWidth = width;
}
person David Storey    schedule 17.05.2013
comment
Привет - спасибо за ответ - я ценю время, которое вы вложили в него. Поскольку цена всегда может быть больше или меньше, предлагаемого вами решения на чистом CSS будет недостаточно. Я ищу решение, использующее блочную модель (или гибкую модель), см. заголовок сообщения. Я действительно ищу способ сделать это только в CSS. Как видите, CSS, который я изначально написал, почти достигает этого. Спасибо еще раз. - person Philip Murphy; 18.05.2013

Я решил, что это работает без JavaScript. Однако он работает только в более современных браузерах, включая Chrome и Opera. В сафари не получится. Он будет работать в Firefox после обновления до последней спецификации. Я, вероятно, смогу заставить его работать в IE10, но я должен изучить это подробнее. Многоточие работает только в Chrome/Safari, поскольку зависит от поставщика.

Демонстрация находится по адресу http://jsfiddle.net/uLm92/1/.

Прежде всего, мы хотим сделать li контейнером flexbox и установить его на 400px, поэтому flex-элементы будут пытаться соответствовать этому размеру (подробнее об этом позже):

li {
    /* make all items inside li as flex items */
    display: -webkit-flex;
    display: flex;

    height: 40px;
    max-width: 400px;
 }

Теперь дочерние элементы являются гибкими элементами, ключом к тому, чтобы метка соответствовала размеру, является установка изображения и цены, чтобы они не были гибкими. Что касается цены, мы знаем, что она всегда должна быть шириной 40xp, поэтому я установил следующее:

.img {
    width: 40px;
    height: 40px;

    -webkit-flex-basis: 40px;
    flex-basis: 40px;
    -webkit-flex-shrink: 0;
    flex-shrink: 0;
 }

Это говорит о том, что предпочтительнее использовать идентификатор 40px и никогда не уменьшать его.

Затем мы также хотим сообщить цене, чтобы она никогда не уменьшалась, а также центрировать анонимный блок (содержимое):

.currency {

    /* make anonymous box vertically centred */ 
    display: -webkit-flex;
    display: flex;

    -webkit-align-items: center;
    align-items: center;

    /* make sure it never shrinks */ 
    -webkit-flex-shrink: 0;
   flex-shrink: 0;
}

Наконец, мы также хотим центрировать текст метки. Поскольку вам нужен хак с многоточием, я использовал старый синтаксис Flexbox для WebKit. Без использования старого flexbox свойство line-clamp не работает:

.этикетка {

/* need to use old flexbox for line-clamp to work
   it is a *horrible hack* */
display: -webkit-box;
display: flex;

-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow : hidden;
text-overflow: ellipsis;

-webkit-box-pack: center;
align-items: center; 

}

Поскольку два других элемента никогда не уменьшатся, элемент .label — единственный, который может это сделать, поэтому он уменьшается в размере, если не осталось места.

person David Storey    schedule 17.05.2013
comment
Привет dstorey, еще раз спасибо за ваши усилия. Однако, как указано в исходном вопросе (Примечание: необходимо работать только в браузерах Chrome и Safari на основе webkit), мне нужно решение для работы как в Chrome, так и в Safari, поскольку оно должно работать на устройствах Android и iOS. Я думаю, что мы сталкиваемся с ограничением CSS. - person Philip Murphy; 20.05.2013
comment
Flexbox может делать то, что вы хотите, но, к сожалению, Safari — нет. Его реализация Flexbox недостаточно хороша. Он не поддерживает такие вещи, как возможность сжимать элемент без его увеличения. Вы можете добавить больше запасных вариантов, чтобы он в основном работал в Safari, но вы не сможете правильно сжимать объекты. Это не ограничение CSS; это ограничение Safari. - person David Storey; 20.05.2013