【问题标题】:Make responsive container snap to elements as it resizes使响应式容器在调整大小时与元素对齐
【发布时间】:2013-09-26 07:16:42
【问题描述】:

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

JSFiddle

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

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

不好:

好:

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

【问题讨论】:

  • 我认为您将需要更复杂的东西,也许需要 JS。也许有一个支持这个的库。
  • @Enzino 与 Stefan Henze 的回答相同的问题。这会导致容器右侧出现很大的空白空间。我希望容器在无法容纳另一个元素时缩小。

标签: javascript html css responsive-design


【解决方案1】:

这是另一个比 ScottS 简单一点的解决方案。它不需要任何定位或使用::before::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、Chrome、Firefox 和 IE 11 中测试。

【讨论】:

    【解决方案2】:

    纯 CSS(一些限制)

    此解决方案基于对another solution for a similar problem I gave elsewhere 的修改。

    Here is the fiddle.

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

    一点解释

    基本上,每个.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;
    }
    

    【讨论】:

    • 太棒了。还不完全确定它是如何工作的,但它正是我所需要的。
    • @jbabey:我添加了一些解释以帮助您更好地理解“这是如何工作的”的更新。
    【解决方案3】:

    删除:

    white-space: nowrap;
    

    来自 .itemBar

    并添加

    text-align:justify;
    

    到 .itemContainer

    这样,其他放不下的东西会掉到下一行,但空间会平均分配。

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

    【讨论】:

    • 很高兴它确实解决了。我可以将我的答案标记为正确吗? :)
    • 是的,当然可以,但要注意应用 *display:inline;缩放:1;为了在ie7中正常工作。我还想补充一点,一旦视口大小超过 1336px,父容器中就会出现空白。
    【解决方案4】:

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

    如果你足够幸运并且知道物品的高度,你可以将容器设置为固定高度和overflow: hidden,让流到下一行的物品不显示出来。

    jsfiddle example

    【讨论】:

    • 是的,浮动你的元素,修复你的容器高度 + 隐藏溢出。
    • 这会导致部分元素不显示,但您仍然会在容器右侧获得空白空间,对吧?
    • 是的,此解决方案不会缩放元素以耗尽可用空间。据我所知,没有解决方案可以仅使用 HTML 和 CSS 来解决这个问题。您当然可以使用 JavaScript 来做到这一点,但是 - 鉴于我不知道您对这个功能的用途 - 我宁愿选择一个简单的解决方案。如果容器(jsfiddle 中的itemContainer)没有边框,它在光学上也可能是可行的。此外,如果您需要针对不同的设备进行优化,请选择宽度以使元素在大多数分辨率下填满空间。
    猜你喜欢
    • 2020-11-25
    • 2010-11-26
    • 2015-07-17
    • 2016-08-15
    • 1970-01-01
    • 1970-01-01
    • 2014-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多