Как получить гибкую сетку плиток с расширителем на всю ширину страницы при щелчке плитки

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

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

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

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

введите описание изображения здесь

Может ли кто-нибудь предложить здесь хороший подход с использованием гибкости?


person Jablalr    schedule 25.05.2019    source источник
comment
Хорошо, благодаря @Hoargarth я добился некоторого прогресса с этим. Однако у меня он не работает должным образом. Итак, мы создали новый скрипт (на основе этой работы), который иллюстрирует то, что я вижу на своей стороне, когда пытаюсь интегрироваться.   -  person Jablalr    schedule 25.05.2019
comment
jsfiddle.net/es80mx5o   -  person Jablalr    schedule 25.05.2019
comment
Пожалуйста, разместите достаточно кода, чтобы воспроизвести проблему в самом вопросе.   -  person Michael Benjamin    schedule 26.05.2019
comment
@Michael_B, спасибо, что нашли время, чтобы посмотреть на мой вопрос. Пересмотренный скрипку размещен выше мой пытается предоставить как можно больше информации, как это возможно! На основании ответа по Hoargarth, я пытался использовать свое решение, но он не был работать в реагирующей случае (или без использования явных размеров), так что я создал скрипку выше, чтобы проиллюстрировать то, что я вижу. Надеюсь, что имеет смысл? Спасибо!   -  person Jablalr    schedule 26.05.2019
comment
Да, в этом есть смысл. Но то, что я хочу сказать, что все соответствующий код принадлежит в самом вопросе, а не на стороннем сайте. Что делать, если этот сайт один день банкрот? Ваш вопрос, то становится бесполезным для посетителей в будущем. Рассмотрим размещение кода в стека сниппет.   -  person Michael Benjamin    schedule 26.05.2019


Ответы (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>

person Hoargarth    schedule 25.05.2019
comment
Большое спасибо за такой всеобъемлющий ответ. Я пытаюсь адаптировать его к тому, что я currentley есть, но без успеха. Основная проблема, кажется, что вы используете фиксированную высоту / ширину и поле. Мой существующий отзывчив и т.д ... и использует 100% экрана. Кроме того, каждая отдельная плитка имеет переменную высоту (на основе его содержания), но каждый сделаны быть одинаковой высоты с помощью гибкого: 1 в моем случае. Я обновил свою скрипку, так что вы можете получить лучшее представление о том, что я вижу, когда я пытаюсь своим подходом! Любые идеи? - person Jablalr; 25.05.2019
comment
К сожалению, я совершенно забыть думать о отзывчивым в этом случае ... Это немного Hacky, чтобы это сделать, но вы могли бы попытаться получить высоту элементов и расположите его с $ (элемент). CSS (). Таким образом, вы можете динамически получить высоту и задать поля для него. Постараюсь скрипка то позже, и пусть вы знаете об этом. - person Hoargarth; 25.05.2019
comment
Это было бы блестящим, спасибо за много! Я, конечно, должен вам несколько сортов пива, если вам удастся выяснить это !! - person Jablalr; 26.05.2019
comment
@Jablalr Жаль, что это заняло так много времени ... Я обновил свой ответ выше, теперь он должен быть в полной мере реагировать. Вы должны даже быть в состоянии установить высоту гибкой, если вы удалите жесткую высоту. - person Hoargarth; 30.05.2019
comment
Привет @Hoargarth, что отлично! Именно то, что я искал! Благодаря Су много! - person Jablalr; 31.05.2019
comment
@Jablalr Рад, что смог помочь :) - person Hoargarth; 31.05.2019