【问题标题】:How to insert a div in between flexbox rows and keep everything responsive?如何在 flexbox 行之间插入一个 div 并保持一切响应?
【发布时间】:2016-11-30 14:01:31
【问题描述】:

我尝试使用 flexbox,就像 flexbox 一样可以保持响应,但我很快发现在换行时不可能有选择地在行之间放置一个 div。

尝试通过 inline-block 而不是使用 flexbox 来实现,如果我忽略保持页面响应,它可以正常工作。但这就是问题的症结所在;我需要它保持响应。

无论行中有多少项目,它都应在所选(单击)图片所在行的行下方显示生物行。如果在不同的行中选择了图片,则将关闭原始 bio 行,并在新选择的图片行下方的行中重新打开。

这是我为 flexbox 管理的最接近的:

    .container {
        max-width: 1220px;
        border: 5px solid black;
        display: flex;
        margin: 0 auto;
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        justify-content: center;
    }
    
    .item {
        border-width: 1px;
        border-style: solid;
        border-color: black;
        width: 200px;
        height: 300px;
    }
    
    .one {
        background: #B5AC01;
    }
    .two {
        background: #ECBA09;
    }
    .three {
        background: #E86E1C;
    }
    .four {
        background: #D41E45;
    }
    .five {
        background: #D41EFF;
    }
    .six {
        background: #D4FF45;
    }

    body {
        margin: 0px;
        padding: 0px;
    }
<div class="container">
  <div class="item one"></div>
  <div class="item two"></div>
  <div class="item three"></div>
  <div class="item four"></div>
  <div class="item five"></div>
  <div class="item six"></div>
  <div class="item four"></div>
  <div class="item five"></div>
  <div class="item six"></div>
  <div class="item one"></div>
  <div class="item two"></div>
  <div class="item three"></div>
</div>

这没有奏效,因为能够找到一行并在这些行之间插入一个 div 显然是一个难题。所以我改变了策略并尝试了 inline-block,结果发现虽然它不那么复杂,但它仍然很复杂。

.container {
  max-width: 1220px;
  border: 5px solid black;
  margin: 0 auto;
  font-size: 0; 
}
    
.item {
  display: inline-block;
  width: 200px;
  height: 300px;
  margin: 0px;
  padding: 0px;
  border: 1px solid black;
  font-size: 14pt;
  color: white;
  text-align: center;
  line-height: 300px;
}

.bio {
  height: 500px;
  width: 100%;
  background: #333;
  color: white;
  font-size: 24pt;
  text-align: center;
  line-height: 500px;
}

.selected {
  box-shadow: inset 0 0 10px #000000;
  font-weight: 800;
}

.row {
  display: inline-block;
  font-size: 0; 
}

.subrow {
  display: inline-block;
  font-size: 0; 
}
    
.one {
  background: #B5AC01;
}

.two {
  background: #ECBA09;
}

.three {
  background: #E86E1C;
}

.four {
  background: #D41E45;
}

.five {
  background: #D41EFF;
}

.six {
  background: #D4FF45;
}

body {
  margin: 0px;
  padding: 0px;
}
<div class="container">
    <div class="row">
        <div class="subrow">
            <div class="item one">Pic</div>
            <div class="item two">Pic</div>
            <div class="item three selected">Clicked Pic</div>
        </div>
        <div class="subrow">
            <div class="item four">Pic</div>
            <div class="item five">Pic</div>
            <div class="item six">Pic</div>
        </div>
    </div>
    <div class="bio">
        Bio goes here with pic
    </div>
    <div class="row">
        <div class="subrow">
            <div class="item four">Pic</div>
            <div class="item five">Pic</div>
            <div class="item six">Pic</div>
        </div>
        <div class="subrow">
            <div class="item one">Pic</div>
            <div class="item two">Pic</div>
            <div class="item three">Pic</div>
        </div>
    </div>
</div>

运气不好。会喜欢仅 CSS/HTML 的解决方案,但如果有必要将其拉下来,我愿意接受 Javascript/jQuery。想法?在此先感谢您的时间。

编辑:有人在下面发布了一个解决方案,建议使用 offsetTop 跟踪 wrappage 以确定在哪里插入 bio 行。虽然它不是 CSS/HTML 唯一的解决方案,但它不是一个糟糕的解决方案。明天早上,当我睡​​得更多时,我将更多地尝试 JS 代码。

【问题讨论】:

  • 那么你想要实现的是在每个偶数位置显示生物行?还是您希望它与同一行中的列元素一起使用?
  • 如果您查看第二个代码 sn-p(更好的是,运行它),您会看到选择了一个“图片”,并且紧挨着该行下方的所选“图片”所在的位置,生物行显示。理想情况下(但尚未实现),如果在原始所选图片的同一行中选择了另一张图片,则生物行保持在同一位置。如果在不同的行中选择了一张图片,则简历将在所选图片下方的一行中关闭并打开。
  • 所以只有一个生物行将被所有图片重复使用?给每张照片一个生物行怎么样?
  • 正确,一次只显示一个生物行。如果在不同的行中选择了一张图片,则简介行会在之前的位置关闭,并在新选择的图片下方的一行中打开。

标签: javascript jquery html css flexbox


【解决方案1】:

$(function(){

  $('.item').click(function() {
    var $this = $(this);
    
    $('.selected').removeClass('selected');
    $this.addClass('selected');

    moveBio();
  });
  
  function moveBio() {

    var $bio = $(".bio");    
    var itemsPerRow = 0;

    $bio.hide(); // hide so doesn't affect calculations

    var firstItem = $('.item').eq(0);
    var itemTop = firstItem.position().top;
       
    $('.item').each(function(i) { // loop till we hit next row
      if($(this).position().top != itemTop) {
            itemsPerRow = i;
            return false;
        }   
    });
    
    selectedIndex = $(".item").index($('.selected')[0]);
    selectedRowNum = Math.floor(selectedIndex / itemsPerRow) + 1;
    
    $(".bio").insertAfter($(".item").eq((selectedRowNum * itemsPerRow) - 1)).show();    
  }
  
  $(window).resize(function() {
    $(".bio").hide(); // hide Bio so it doesn't interfere with the flex layout during resize
    clearTimeout(window.resizedFinished);
  
    window.resizedFinished = setTimeout(function(){
        moveBio(); // show Bio again now that resize has stabilised
    }, 250);
  });
  
});
.container {
        max-width: 1220px;
        border: 5px solid black;
        display: flex;
        margin: 0 auto;
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        justify-content: center;
        position: relative;
    }
    
    .item {
        border-width: 1px;
        border-style: solid;
        border-color: black;
        width: 200px;
        height: 300px;
    }
    
.bio {
  height: 500px;
  width: 100%;
  background: #333;
  color: white;
  font-size: 24pt;
  text-align: center;
  line-height: 500px;
}
    .one {
        background: #B5AC01;
    }
    .two {
        background: #ECBA09;
    }
    .three {
        background: #E86E1C;
    }
    .four {
        background: #D41E45;
    }
    .five {
        background: #D41EFF;
    }
    .six {
        background: #D4FF45;
    }
    .selected {
        box-shadow: inset 0 0 10px #000000;
        font-weight: 800;
    }
    body {
        margin: 0px;
        padding: 0px;
    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="container">
  <div class="item one"></div>
  <div class="item two"></div>
  <div class="item three"></div>
  <div class="item four"></div>
  <div class="item five"></div>
  <div class="item six selected"></div>
    <div class="bio">
        Bio goes here with pic
    </div>  
  <div class="item one"></div>
  <div class="item two"></div>
  <div class="item three"></div>
  <div class="item four"></div>
  <div class="item five"></div>
  <div class="item six"></div>
</div>

添加了动态浏览器调整大小

这是一个更容易调整大小的示例:http://jsbin.com/wamisiliza/edit?output

【讨论】:

  • 添加了带有动态浏览器大小调整的新 jsbin 示例
  • 在我最初的帖子下方查看我的评论,这应该有助于阐明生物的工作原理。为了节省您的时间,我将在这里重申。它基本上只显示一个生物行。如果单击图片,则会在单击图片所在行的下方显示生物行。如果要在不同的行中显示生物行,则关闭原始生物行,然后在单击的图片正下方的行中重新打开。有人发布了一个解决方案,建议使用 OffsetTop 来确定 wrappage 以使其响应。不错的主意。
  • 这与您的问题完全不同-“如果每行有 6 个项目,则每 6 个项目显示一个 bio 行。如果每行包含 3 个项目,则每 3 个项目显示一个 bio 行。 ...”
  • 好收获,漫长的一天。修正后澄清。
  • 按预期工作;没想到你会编写整个shebang,但仍然非常感谢!我已将此标记为解决方案,因为我将继续使用它。以供将来参考,仅使用 HTML/CSS 没有好方法吗?
【解决方案2】:

这是一个有趣的问题。我不知道CSS。但是我想出了一个相当复杂的javascript方法。

首先获取所有项目的数组,就像您的第一个示例一样。并且对于每个项目,将offsetTop 与前一个项目进行比较,如果值不相等,则在两行之间插入一个新的 Bio 行。

抱歉英语不好,期待更好的答案。

【讨论】:

  • 有趣的解决方案。单击图片时,可以关闭 bio 行,使用 $(this) 获取项目的句柄,通过 .closest 找到最近的 .row,然后遍历子项以识别每个项目的 offsetTop 以确定包装,并使用如果然后条件确定在哪里插入生物。这可能只是工作。我希望有一个干净的 CSS 解决方案,但我也可以使用 JS 解决方案。我会尝试一下,谢谢你的想法!
猜你喜欢
  • 2021-08-04
  • 1970-01-01
  • 2018-12-09
  • 2016-11-02
  • 2012-05-19
  • 2020-10-24
  • 2022-09-27
  • 1970-01-01
  • 2014-04-29
相关资源
最近更新 更多