Using box model to contain items within its parent div

大兔子大兔子 提交于 2020-01-02 04:05:05

问题


Using the following HTML and CSS3 rules, I'm trying to make sure that the following criteria are adhered to:

I have all of the criteria working except for item 1 where the children are exceeding their parent's width. Question: How to keep children within their parent?

  1. li items cannot exceed their parent width i.e. 400px
  2. img, label, and currency content must be centred vertically within their span
  3. currency should not wrap and should always be displayed in full
  4. currency should always be displayed as close as possible to the label span.
  5. the label text should be clamped at 2 lines with ellipsis displayed where it exceeds 2 lines.

Note: Only needs to work in Chrome and Safari webkit-based browsers.

It should look like:

However, it looks like this at the moment:

Any ideas?

********************* JS Fiddle example ************************

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

回答1:


The following will work, providing the price doesn't get wider:

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

I simply converted the margin-right to pixels so I knew the space taken up by the content other than the label, then added a max-width for the remainder:

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

if the price or image are variable width, you will need js to read their widths, remove from 400px and add that value to max-width.

Here is an example using JavaScript to dynamically set the max-width: http://jsfiddle.net/WDjZ3/7/

I haven't checked all dimensions, so that should be added to make it fully accurate, otherwise the margins will make the price no longer fit.

I basically checked the width of the other elements:

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

I then removed this width from 400px, and set the maxWidth:

for (var i=0; i<imgs.length; i++) {
    var width = 400 - (getWidth(imgs[i]) + getWidth(currencies[i])) + "px"; 
    labels[i].style.maxWidth = width;
}



回答2:


I’ve solved this to work without JavaScript. However, it only works in more modern browsers, including Chrome and Opera. It will not work in Safari. It will work in Firefox once it updates to the latest spec. I can probably get it to work in IE10, but I have to look into that more. The ellipsis only works in Chrome/Safari as it is vendor specific.

The demo is at http://jsfiddle.net/uLm92/1/

First of all we want to make the li as a flexbox container and set it to 400px, so the flex items will try to fit that size (more on that later):

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

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

Now the child items are flex items, the key to getting the label to fit is setting the image and the price to not flex. For the price, we know it wants to always be 40xp wide, so I set the following:

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

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

This says that the preferred with id 40px and never make it smaller.

Then we want to also tell the price to never shrink, and to also centre the anonymous box (the content):

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

Lastly, we want to also center the label text. As you need the ellipsis hack, I've used the old Flexbox syntax for WebKit. Without using old flexbox, the line-clamp property does not work:

.label {

/* 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; 

}

As the other two items will never shrink, the .label element is the only one that can, so it reduces in size if there is no space left.



来源:https://stackoverflow.com/questions/16213492/using-box-model-to-contain-items-within-its-parent-div

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!