如何具有Flex的图块网格,并在单击图块时使用全页宽度扩展器

时间:2019-05-25 14:20:07

标签: html css css3 flexbox

在正常的宽度/大小屏幕上,我有一个3 x 3的网格,其中包含摘要状态信息。我正在使用CSS Flex,并且在较小的屏幕上都可以很好地工作,折叠成2列的网格,最后在移动设备上只有一列。

但是,我试图找出一种方法,可以单击任何网格元素以“额外的细节”打开其下方的扩展器。扩展器显然应该是屏幕的整个宽度。

因此,例如,在具有3x3网格的桌面上,如果单击第一个框,则希望扩展器在第一行下方扩展,以填充屏幕的整个宽度。

但是,如果我在单击时仅显示全宽div显示器,它只会将第二和第三块瓷砖向下推。参见图片以获得更好的解释!

enter image description here

有人可以在这里建议使用flex的好方法吗?

1 个答案:

答案 0 :(得分:1)

好,这是更新的版本: 大多数内容都应该评论,但我很难解释。因此,请随时询问是否不清楚。

对于HTML部分: 您需要将“ Clickable”项和可扩展容器分成两个单独的flex项。它们的顺序无关紧要

对于CSS部件: 只需将可扩展容器的宽度设置为100%,然后用display: none

隐藏即可

JavaScript(那是棘手的部分): 1.对于您单击的那个项目,您需要当前行的最后一个项目的编号 2.单击后插入可扩展的弹性项目 3.显示展开式

要在调整窗口大小并进入另一个视口时重新定位,只需在“每行项目”发生变化时再次触发单击即可。

提琴:https://jsfiddle.net/Hoargarth/mfg0vshL/

//click event to expand the expandable
$('.flex-item').on('click', function(){
    //hide previous opened expandables
    $('.flex-item').removeClass('active');
    $('.flex-expandable').slideUp();
    //get target data
    var target = $(this).attr('data-target'); 
    //toggle the container
    var $triggered = $(this);
    var $triggeredElement = $('.flex-expandable[data-target='+ target +']');
    positionExpandableElement($triggered, $triggeredElement);
    $triggered.addClass('active');
    $triggeredElement.slideDown();
});

//we need to check on resize how many items are pe row, if it changes, trigger a click on a already opened item, so it positions itself at the right position
var containerWidth = $('.flex-container').outerWidth();
var itemWidth = $('.flex-item').outerWidth();
var itemsPerRow = Math.floor(containerWidth / itemWidth);

$(window).resize(function(){
    containerWidth = $('.flex-container').outerWidth();
    itemWidth = $('.flex-item').outerWidth();
    var newItemsPerRow = Math.floor(containerWidth / itemWidth);
	if(itemsPerRow != newItemsPerRow){
  	    itemsPerRow = newItemsPerRow;
        $('.flex-item.active').trigger('click');
    }
})

function positionExpandableElement(triggered, element) {
	/*first determine at which position your expandable element has to be, should be the first element of next row from triggered element.
  For this we need to know how many elements currently are in a row. Then you can position it after that element*/
  
  //get the item number where you have to insert after
  var allFlexItems = $('.flex-item');
  var itemsData = []; //we need an array of data-targets to get the number of element from the array index
  $.each(allFlexItems, function(key, el){
  	itemsData.push($(el).attr('data-target'));
  });
  var elNumber = $.inArray($(triggered).attr('data-target'), itemsData)
  //elNumber now tells us the position of the element that got triggered
  //now we can calculate where we have to insert our expandable
  var rowNumber = Math.floor(elNumber / itemsPerRow);
  var insertAfter = (itemsPerRow * rowNumber) + itemsPerRow - 1; //we add itemsPerRow because we allways need to skip the first row, -1 because array starts at 0
  //now that we now the last items number (even in responsive), we can insert our expandable on click after that element
  $(element).insertAfter($('.flex-item')[insertAfter]);
}
.flex-container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  width: 100%;
}

.flex-item {
  width: 100%;
  height: 100px;
  background-color: blue;
  margin-bottom: 15px;
  cursor: pointer;
}

.flex-expandable {
  display: none;
  width: 100%;
  height: 100px;
  background-color: orange;
  margin-bottom: 15px;
}

@media (min-width: 400px) {
  .flex-item {
    width: 45%;
  }
}

@media (min-width: 600px) {
  .flex-item {
    width: 30%;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- for data-target you can use anything you want. Even something like data-target="this-is-my-first-container", as long as the expandable got the same like the item and it should be unique -->

<!-- The order of the Items dosn't matter, you could even randomize them -->

<div class="flex-container">
  <div class="flex-item" data-target="1"></div>
  <div class="flex-item" data-target="2"></div>
  <div class="flex-item" data-target="3"></div>
  <div class="flex-item" data-target="4"></div>
  <div class="flex-item" data-target="5"></div>
  <div class="flex-item" data-target="6"></div>
  <div class="flex-item" data-target="7"></div>
  <div class="flex-item" data-target="8"></div>
  <div class="flex-item" data-target="9"></div>
  <div class="flex-expandable" data-target="1"></div>
  <div class="flex-expandable" data-target="2"></div>
  <div class="flex-expandable" data-target="3"></div>
  <div class="flex-expandable" data-target="4"></div>
  <div class="flex-expandable" data-target="5"></div>
  <div class="flex-expandable" data-target="6"></div>
  <div class="flex-expandable" data-target="7"></div>
  <div class="flex-expandable" data-target="8"></div>
  <div class="flex-expandable" data-target="9"></div>
</div>