12

我有一个包含恒定宽度项目的动态宽度容器 div。我希望能够调整容器的大小,以便它只显示整个项目,而不是将右侧的项目切成碎片。

JSFiddle

例如,用户的屏幕可能会呈现 5 个项目:

在此处输入图像描述

如果该用户开始缩小他们的屏幕宽度,一旦栏不再足够宽以容纳 5 个完整项目,我希望它缩小到仅显示 4 个项目。

坏的:

在此处输入图像描述

好的:

在此处输入图像描述

我知道这可以通过使用 CSS3 媒体查询来实现,但我想避免为每个不同数量的元素编写不同的断点。我还想避免使用 javascriptresize事件处理程序,但我不确定没有它是否可行。

4

4 回答 4

13

纯 CSS(一些限制)

该解决方案基于对我在其他地方给出的类似问题的另一个解决方案的修改。

这是小提琴。

它涉及重叠伪元素的复杂关系来创建边界,这可能导致解决方案对在其中可能或不可能在其中完成的事情有一定的限制(复杂的背景将是一个问题,也是必要的对于某些定位方面)。然而,它在给定的情况下起作用。

一点解释

本质上,每个元素都使用and元素.item构建自己的顶部/底部边框部分,前者与 相关,后者与自身相关(需要在行的末尾创建最后一点边框) . 此外,它还创建了右边框的“灵活”位置,以便在元素移出视图时为其提供所需的响应能力。这就是为什么必须与自身相关,也是为什么必须使用每个元素的背景来“隐藏”前一个元素的右边框。:after:before.itemContainer.item:before:before:before.item:after:before

由于我们不通过 css 知道任何给定点的“计数”关于哪个元素是显示中的“最后一个”,因此:before必须显示所有元素,但我们不希望它们都有右边框,因此为什么:after覆盖它们的需要。当一个元素向下移动到下一行时,它:after不再覆盖现在成为最后一个显示元素的右边框,显示该边框将用作整个组的“右”边框。

HTML(匹配你原来的小提琴)

<div class="itemBar">
    <div class="itemContainer">
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>     
        <div class="item">6</div>
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
        <div class="item">10</div>     
    </div>
</div>

主要项目的CSS

.itemBar {
    display: inline-block;
    width: 50%; /* some width can be set, does not need to be this */
}

.itemContainer {
    position: relative; /* :after pseudo-elements are positioned off this */
    z-index: 1; /* needed for pseudo-element interaction */
    overflow: hidden;
    display: inline-block;
    max-height: 68px;
    width: 100%;
    border-left: 1px solid black; /* left border is supplied by this */
}

.item {
    width: 60px;
    height: 62px;
    display: inline-block;
    margin: 2px;
    border: 1px solid black;
    /* NOTE: CANNOT be given positioning  */
}

伪元素的 CSS

.item::after {
    content: '';
    position: absolute; /* will position off itemContainer */
    z-index: -1; /* push it to the background */
    top: 0; /* set it to top of itemContainer */
    bottom: 0; /* set it to bottom of itemContainer */
    margin-left: -100%; /* shove it past the far left edge of itemContainer */
    /* next, use padding to bring it back to its position at the end
       of the text string of .item */
    padding-left: 100%;
    /* next, add enough padding on the right to compensate for the right
       padding, right margin, and right border of .item */
    padding-right: 3px; 
    /* next, create the top and bottom border of "container", 
       in conjunction with the :before; so this is a pseudo-border for 
       .itemContainer being created by the .item elements */
    border-top: 1px solid black;
    border-bottom: 1px solid black;
    background: #fff; /* hide other :before borders */
}

.item:before { /* make right border */
    content: '';
    padding-top: 66px; /* give it .itemContainer height minus border heights */
    width: 100%;
    margin-top: -3px; /* .item top margin + border width */
    margin-left: -100%; /* pull the text in .item back into position */
    margin-right: 0;
      /* next, push this behind the background with an even lower z-index
        to hide it if it is not the right most element beign used to 
        form the right border */   
    z-index: -2;
    float: right; /* get the before element to the right */
    position: relative; /* needs to be adjusted in position */
    right: -4px; /* move it same as padding-right of the after element */
    display: block; /* give it a display */
      /*  next, use it to build the fake right border and also the fake
          final top/bottom borders of the of itemContainer */
    border-right: 1px solid black;
    border-top: 1px solid black;
    border-bottom: 1px solid black;
}
于 2013-09-25T03:44:04.083 回答
4

消除:

white-space: nowrap;

来自 .itemBar

并添加

text-align:justify;

到 .itemContainer

这样,其他不适合的项目将落到下一行,但空间将平均分配。

演示:http: //jsfiddle.net/rDxRt/4/

于 2013-09-24T18:53:12.247 回答
3

您可以让容器中的物品浮动。这样,如果容器变小,它们将浮动到下一行。

如果您足够幸运并且知道项目的高度,您可以将容器设置为固定高度,overflow: hidden并使流到下一行的项目不显示。

jsfiddle 示例

于 2013-09-20T19:43:38.823 回答
0

这是另一个比 ScottS 更简单的解决方案。它不需要任何定位或使用::beforeor ,而是依赖于不超过最后一个可见项目::after的事实。::first-line

标记

<div class="itemContainer">
  <div class="item">1</div><div
  class="item">2</div><div
  class="item">3</div><div
  class="item">4</div><div
  class="item">5</div><div 
  class="item">6</div><div 
  class="item">7</div><div 
  class="item">8</div><div 
  class="item">9</div><div 
  class="item">10</div>
</div>

请注意,此解决方案对元素间空白很敏感,因此您需要删除连续.items 之间的换行符/空格。我在上面的标签名称和类之间换行以使其更具可读性。

CSS

.itemContainer {
    overflow: hidden;
    height: 70px; /* .item's offset height + margin */
    /* you can constrain the width of this any way you like */
}
.itemContainer::first-line {
    font-size: 70px; /* needs to be at least as big as .wrap height */
    line-height: 0px; /* fixes oddities in Firefox */
    background: black; /* "border" color */
}
.item {
    display: inline-block;
    vertical-align: text-top; /* this minimizes the font-size required  above */
    margin: 10px; /* include desired "border" size of .itemContainer */
    box-shadow: 0 0 0 9px white; /* spread = desired margin */
    background: white; /* needs an opaque background */
    /* reset font-size and line-height */
    font-size: 1rem;
    line-height: 1.5;
    /* set your item size and borders however you like */       
    height: 50px;
    width: 50px;
    border: 1px solid red;
    box-sizing: border-box;
}
.item::first-line {
    font-size: 1rem; /* fix IE precedence */
}
.item + .item {
    margin-left: 0; /* inline-block margins don't collapse */
}

结果

来自 Safari 的屏幕截图,仅限于 10 个项目中的 8 个

在 Safari、Chrome、Firefox 和 IE 11 中测试。

于 2016-08-28T05:33:46.460 回答