【问题标题】:How to have Flex grid of tiles, with full page width expander when tile 'clicked'如何在“单击”磁贴时拥有 Flex 磁贴网格,并带有全页宽度扩展器
【发布时间】:2019-10-11 19:47:13
【问题描述】:

在正常宽度/尺寸的屏幕上,我有一个 3 x 3 的网格,其中包含摘要状态信息。我正在使用 CSS Flex,并且在较小的屏幕上运行良好,在移动设备上折叠成 2 列网格,最后是单列。

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

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

但是,如果我只是在点击时显示全宽 div,它只会将第二个和第三个图块向下推。查看图片以获得更好的解释!

谁能在这里推荐一个使用 flex 的好方法?

【问题讨论】:

  • 好的,感谢@Hoargarth,我在这方面取得了一些进展。但是,它对我来说不能正常工作。因此,创建了一个新的 Fiddle(基于这项工作)来说明我在尝试集成时看到的结果。
  • 请发布足够的代码来重现问题本身的问题。
  • @Michael_B,感谢您花时间查看我的问题。上面发布的修改后的小提琴是我试图提供尽可能多的信息!根据 Hoargarth 的回复,我尝试使用他的解决方案,但它不适用于响应式案例(或不使用显式尺寸),因此我创建了上面的小提琴来说明我所看到的。希望这是有道理的?谢谢!
  • 是的,这是有道理的。但我要说的是,所有相关代码都属于问题本身,而不是第三方网站。如果那个网站有一天破产了怎么办?然后,您的问题对未来的访问者毫无用处。考虑将您的代码发布到stack snippet

标签: html css flexbox


【解决方案1】:

好的,这是一个更新的版本: 大多数东西都应该被评论,但我很不擅长解释。所以如果有什么不清楚的地方欢迎追问。

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

对于 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 always 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>

【讨论】:

  • 非常感谢您提供如此全面的回复。我正在尝试使其适应我目前拥有的东西,但没有成功。主要问题似乎是您使用的是固定的高度/宽度和边距。我现有的是响应式等......并且正在使用 100% 的屏幕。此外,每个单独的图块都有一个可变的高度(基于其内容),但在我的例子中,每个图块都通过 flex:1 设置为相同的高度。我已经更新了您的小提琴,以便您在尝试您的方法时可以更好地了解我所看到的内容!有什么想法吗?
  • 抱歉,在这种情况下,我完全忘记考虑响应式了...完成此操作有点“hacky”,但您可以尝试获取元素的高度并使用 $(元素)'.css()。因此,您可以动态获取高度并为其设置边距。稍后我会尝试摆弄一些东西并让你知道。
  • 那太好了,非常感谢!如果你能弄明白,我一定会欠你几杯啤酒的!!
  • @Jablalr 抱歉,花了这么多时间......我已经更新了上面的答案,现在应该可以完全响应了。如果您移除硬高度,您甚至应该能够灵活地设置高度。
  • 嗨@Hoargarth,太完美了!正是我想要的!非常感谢!
【解决方案2】:

@hoargath 的目的只需要对最后一个不完整的行进行一次修复:

insertAfter = insertAfter > (allFlexItems.length - 1) ? allFlexItems.length - 1 : insertAfter;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-03
    • 2011-07-16
    • 2022-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-25
    相关资源
    最近更新 更多