Как использовать Flex-сетку плиток с расширителем полной ширины страницы при нажатии на плитку - PullRequest
0 голосов
/ 25 мая 2019

На обычном экране ширины / размера у меня есть сетка 3 х 3 плитки, которые содержат сводную информацию о состоянии. Я использую CSS Flex, и все работает очень хорошо на небольших экранах, сворачиваясь в сетку из 2 столбцов и, наконец, в один столбец на мобильных устройствах.

Однако я пытаюсь найти способ, как щелкнуть любой элемент сетки, чтобы открыть расширитель под ним с «дополнительной детализацией». Расширитель, очевидно, должен быть на всю ширину экрана.

Так, например, на рабочем столе с сеткой 3х3, если я нажму на первое поле, я хочу, чтобы расширитель расширился ниже первого ряда, заполняя всю ширину экрана.

Однако, если я просто показываю div по ширине при щелчке, он просто толкает 2-ю и 3-ю плитки внизу. Смотрите изображение для лучшего объяснения!

enter image description here

Кто-нибудь может предложить хороший подход, используя flex?

1 Ответ

1 голос
/ 25 мая 2019

Хорошо, вот обновленная версия: Большая часть материала должна быть прокомментирована, но я довольно плохо объясняю. Поэтому не стесняйтесь спрашивать, если что-то не понятно.

Для части HTML: Вам нужно разделить ваш «кликабельный» предмет и расширяемый контейнер на два отдельных флекс-элемента. Порядок их не имеет значения

Для CSS-части: Просто дайте этому расширяемому контейнеру ширину 100% и скройте их с помощью display: none

Javascript (вот сложная часть): 1. Для того элемента, который вы щелкнули, вам нужен номер последнего элемента в текущей строке 2. После этого нажмите расширяемый элемент Flex 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...