【问题标题】:Photowall with double sized highlight pictures带有双倍尺寸高光图片的照片墙
【发布时间】:2017-04-21 21:16:24
【问题描述】:

我们正在开发一个图片库网站,但找不到以下问题的解决方案。

图片墙包含多张图片。一些图像(n 百分比)应突出显示并在墙上显示双倍尺寸。

问题是,我不知道要填补大图留下的空白,因为它是一个新行。

任何想法。

我在这里为这个示例创建了一个小提琴:Fiddle

    <body>
  <div class="size1">
  &nbsp;
  </div>
    <div class="size1">
  &nbsp;
  </div>
    <div class="size2">
  &nbsp;
  </div>
    <div class="size1">
  &nbsp;
  </div>
    <div class="size1">
  &nbsp;
  </div>
     <div class="size1">
  &nbsp;
  </div>
    <div class="size1">
  &nbsp;
  </div>
     <div class="size1">
  &nbsp;
  </div>
    <div class="size1">
  &nbsp;
  </div>
      <div class="size1">
  &nbsp;
  </div>
     <div class="size1">
  &nbsp;
  </div>
    <div class="size1">
  &nbsp;
  </div>
     <div class="size1">
  &nbsp;
  </div>
    <div class="size1">
  &nbsp;
  </div>
</body>

    div {
  background-color: #f00;
  float: left;
}

.size1{
  width: 100px;
  height: 100px;
    margin: 5px;
}
.size2{
  width: 210px;
  height: 210px;
    margin: 5px;
}

【问题讨论】:

    标签: css


    【解决方案1】:

    更新:

    以下浏览器现在原生支持 CSS 网格布局。

    1. 火狐v52

    2. 适用于 Linux、macOS、Windows、iOS 和 Android 的 Chrome v57

    3. Safari v10.1

    4. iOS Safari v10.3

    5. Opera v44


    这种布局要求正是CSS Grid Layout 规范旨在解决的问题。该规范的介绍如下:

    网格布局是一种新的 CSS 布局模型,具有强大的能力来控制框及其内容的大小和位置。与面向单轴的 Flexible Box Layout 不同,网格布局针对二维布局进行了优化:在二维布局中需要内容对齐。

    CSS Grid Layout 的本机浏览器支持可能很快就会开始登陆主流浏览器(如 here 所示),并且目前在某些浏览器中被标记为特色。对于不支持的浏览器,此 JavaScript polyfill 将是必需的。

    作为一个例子,CSS Grid Layout 语法显示在以下 CSS 中:

    HTML

    <div class="wrapper">
      <div class="box">1</div>
      <div class="box">2</div>
      <div class="box">3</div>
      <div class="box">4</div>
      <div class="box box--double">5</div>
      <div class="box">7</div>
      <div class="box">8</div>
      ...
    </div>
    </div>
    

    CSS 使用网格布局模型

    .wrapper {
      width: 600px;
      display: grid;
      grid-gap: 10px;
      grid-template-columns: repeat(7, 100px);
      grid-template-rows: 100px 100px 100px;
      grid-auto-flow: row;
    }
    
    .box {
      background-color: #444;
      color: #fff;
      padding: 20px;
      font-size: 150%;
      margin: 5px;
    }
    
    .box--double {
      background-color: red;
      grid-column: 3 / span 2;
      grid-row: 2 / span 2;
    }
    

    演示

    这是一个 fiddle,它利用 CSS 网格布局 语法(包括 polyfill)来提供一般要点。


    或者,Masonry 可能能够实现这一点,但长期而言,这将始终依赖于 JavaScript。


    响应式网页设计 (RWD)

    CSS Grid Layout 模块包含多项功能,可简化响应式设计的创建。解决 cmets 中提出的问题的两个相关功能是:

    1 Flexible Lengths

    应该使用fr 单位,而不是将相对列宽指定为百分比。 fr 单元的主要好处是,当列数通过媒体查询发生变化时,它避免了手动重新计算百分比 - (您只需更改列数的值) :

    /* Avoid using percentages like this */
    .wrapper {
        grid-template-columns: repeat(7, 14.286%);
        ...
    }
    
    /* Use the 'fr' unit instead */
    .wrapper {
        grid-template-columns: repeat(7, 1fr);
        ...
    }
    

    2 grid-auto-flow-dense

    可以为grid-auto-flow 属性分配三个值,即row、column 和dense。

    .wrapper {
        grid-auto-flow: dense;
        ...
    }
    

    在某些情况下,当使用 row 或 column 值时,可能会在布局中产生不需要的孔/间隙。当指定dense 时,算法会尝试填补这些漏洞/空白,但这有时会改变项目的顺序。此功能与Masonry 根据可用垂直空间将项目放置在不同位置的方式非常相似。

    后驱演示

    这是一个响应式fiddle,它同时使用fr 单位和dense 值来避免布局中的任何间隙/漏洞。


    EDIT(5):更新了支持 CSS 网格布局的浏览器列表。

    EDIT(4):添加了有关 Chrome 57 实施 CSS 网格布局规范的说明。

    EDIT(3):添加了有关 Firefox 52 实施 CSS 网格布局规范的说明。

    EDIT(2):添加有用的 CSS 网格布局功能以实现 RWD

    EDIT(1):将示例代码更改为简洁版本并更新了指向外部小提琴的链接

    【讨论】:

      【解决方案2】:

      这是一个纯 CSS 的解决方案,完全响应,基于 CSS columns

      .columns >div {
        background-color: #f00;
        float: left;
        -webkit-column-break-inside: avoid;
        page-break-inside: avoid;
        break-inside: avoid;
      }
      
      .size1{
        width: 100px;
        height: 100px;
        margin: 5px;
      }
      .size2{
        width: 210px;
        height: 210px;
        margin: 5px;
      }
      .columns {
        width: 660px;
        margin: 0 auto;
        -webkit-columns: 200px 3;
        -moz-columns: 200px 3;
        columns: 200px 3;
        -webkit-column-gap: 0;
        -moz-column-gap: 0;
        column-gap: 0;
      }
      
      @media (max-width: 689px) {
        .columns {
          width: 440px;
          margin: 0 auto;
          -webkit-columns: 200px 2;
          -moz-columns: 200px 2;
          columns: 200px 2;
        } 
      }
      @media (max-width: 459px) {
        .columns {
          display: flex;
          flex-wrap: wrap;
          max-width: 220px;
        }
        .columns div {
          flex: 1 0 auto;
        }
        .columns .size1 {
          flex-basis: calc(50% - 10px)
        }
        .columns .size2 {
          flex-basis: calc(100% - 10px)
        }
      }
      body {
        padding: 0;
        text-align: center;
      }
      
      @media (min-width: 920px) { /* 4 columns */
        .columns {
          width: 880px;
          -webkit-columns: 200px 4;
          -moz-columns: 200px 4;
          columns: 200px 4;
        }
      }
      @media (min-width: 1140px) { /* 5 columns */
        .columns {
          width: 1100px;
          -webkit-columns: 200px 5;
          -moz-columns: 200px 5;
          columns: 200px 5;
        }
      }
      @media (min-width: 1360px) { /* 6 columns */
      .columns {
          width: 1320px;
          -webkit-columns: 200px 6;
          -moz-columns: 200px 6;
          columns: 200px 6;
        }
      }
      @media (min-width: 1580px) { 
        /* respect the principle above to add as many columns as you like */
      }
      <div class="columns">
        <div class="size2"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size2"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size2"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size2"></div>
        <div class="size1"></div>
        <div class="size1"></div>
      </div>

      对于手机媒体查询间隔,我使用了flexbox,但这只是为了表明它是可能的。你真的不必,你可以坚持box-model。

      注意:您可以定义更多的媒体间隔。基本思想是拥有 220px 的倍数,并将其限制为为所有列有足够空间的宽度。

      这是小提琴(我添加它是因为出于某种原因,SO 不允许我将 sn-p 窗口的大小调整到 ~480px 以下,而 jsFiddle 可以。) fiddle here


      此解决方案假定您总是将 2 个小物品配对在一起(因此它们占据 1 行)。如果您想要一个解决方案,让添加内容的人不必满足此条件,并在小项目为single 时自动尝试配对,您需要javascript。


      时间线解决方案(基于 cmets 信息)

      我猜这就是你需要的? (如果您决定更改类名,则需要同时调整 js 和 CSS)。

      $('.timeline .size2').each(function(){
        //moving required number of small'uns so they fill the column
        var prevIndex = $(this).prevAll('.size2,.wrap').eq(0).index(), 
            diff = $(this).index() - (prevIndex + 1), 
            toMove = (3 - (diff  % 3)) %3;
        if (toMove) {
          for (var i = 1; i < toMove + 1; i++) {
            $(this).nextAll('.size1').eq(0).addClass('moved').insertBefore($(this))
          }
        }
        var wrap = $('<div />', {
          class:'wrap'
        })
      
        //wrap 2 small'uns to make a row under a big'un
        for (var i = 0; i < 2; i++) {
          wrap.append($(this).nextAll('.size1').eq(0));
        }
        wrap.insertAfter($(this));
      })
      .timeline [class^="size"] {
        background-color: red;
      }
      
      .size1{
        width: 100px;
        height: 100px;
        margin: 5px;
      }
      .size2{
        width: 210px;
        height: 210px;
        margin: 5px;
      }
      .timeline {
        display: flex;
        flex-direction: column;
        align-content: flex-start;
        height: 330px;
        flex-wrap: wrap;
      }
      .timeline .wrap {
        display: inline-flex;
      }
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      <div class="timeline">
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size2"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size2"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size2"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size1"></div>
        <div class="size2"></div>
        <div class="size1"></div>
        <div class="size1"></div>
      </div>

      【讨论】:

      • 感谢这种方法。不幸的是,我需要基于行的方法,因为我需要基于时间的顺序。
      • 您所需要的可以通过display:flex; flex-direction: column; height: {/* size in px for 3 small boxes */} 实现。我现在不能这样做,我会在大约 8 小时内回复它,如果你仍然需要它,我会提供一个例子(你没有得到另一个答案)。还有……嘿!还有一件事:没有提供有关需求的完整信息,尤其是当它有点复杂时,它真的不酷。你应该尽量减少任何愿意帮助的人的努力。
      • 嘿安德烈,很抱歉额外的努力。阅读您的方法后,我首先遇到了排序问题。非常遗憾。感谢您的参与!下次我会努力的。
      • 使用jQuery 和flexbox 更新了您似乎需要的内容。如果您不使用jQuery,则应该在vanilla 中完成,但对我来说这样更快。另请注意,您应该在部署之前运行CSS 到autoprefixer。无论您如何放置元素,脚本都会调整和移动元素(确保所有间隙都已填满)。
      【解决方案3】:

      我尝试缩短 RobC 的小提琴,并将固定宽度(以像素为单位)替换为以百分比表示的相对宽度。所以它的反应有点快。但是仍然有一些差距,你可以通过一些规则来防止,比如“没有 2 个并排的大盒子”等等。

      HTML

      <div class="wrapper">
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" /> 
        <img src="https://dummyimage.com/300x200/333/fff" class="" /> 
        <img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
        <img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />  
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />  
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
        <img src="https://dummyimage.com/300x200/333/fff" class="" />
      </div>
      

      CSS

      .wrapper {
        width: 100%;
        display: grid;
        grid-template-columns: repeat(6, 16.666%);
        grid-auto-flow: row;
      }
      @media screen and (max-width: 940px) {
        .wrapper {
          grid-template-columns: repeat(5, 20%);
        }
      }
      @media screen and (max-width: 540px) {
        .wrapper {
          grid-template-columns: repeat(3, 33.333%);
        }
      }
      
      .wrapper > img {
        background-color: #444;
        color: #fff;
        border: solid 1px white;
      }
      .box::before {
        content: ' ';
        display: block;
        padding-top: 100%;
      }
      
      .box--double {
        background-color: red;
        grid-column: auto / span 2;
          grid-row: auto / span 2;
      }
      

      The fiddle

      【讨论】:

      • 感谢您玩这个。我用你的小提琴玩了一点,我想,我可以用源数据上的一些规则来弥补差距。我发现,以下规则将尽可能避免出现空白: - 仅显示因子为 3 的列(3、6 或 9 列) - 前三张图片中没有高亮图片 - 避免高亮图片可除以三 -两张精彩照片之间至少有四张照片
      猜你喜欢
      • 2014-11-23
      • 1970-01-01
      • 1970-01-01
      • 2015-12-31
      • 2011-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-23
      相关资源
      最近更新 更多