I’m using grid-template-columns: repeat(auto-fit, 250px)
to keep grid items 250px
wide but automatically adjust number of row-items according to screen-width. Now I want that when I hover over an item, it expands taking a bit of its sibling’s space, with its sibling getting shrunk. By console.log()
, I found nextElementSibling
that can be used. So I’m thinking of something like-
function expand(card){
card.setAttribute("style","width: 300px;");
card.nextElementSibling.setAttribute("style","width: 200px");
}
function restore(card){
card.setAttribute("style","width: 250px;");
card.nextElementSibling.setAttribute("style","width: 250px");
}
This seems pretty bad (I guess!) because I need to manage corner items separately and hence need to know the current number of items in a row. Also, when I hover over a card, the card does expand but because of repeat(auto-fit,250px)
, the card intersects its sibling because the individual cells remain fixed (250px
).
How can I solve the issues? Or any better suggested solutions?
Here is my git repository.
Edit 1- As to clarify my issues:
- How to manage the corner items, i.e., for an item in the right corner I want its previous sibling shrink; not the next.
- The cells remain fixed, i.e., the expanding item intercepts the shrinking item’s border-
becomes
So how to deal with this behavior caused by auto-fit,250px
?
Advertisement
Answer
I honestly tried to solve it using grid-template-columns: repeat(auto-fit, minmax(250px,auto));
and a different size of child elements, but in’s too unstable and not working that way. But I don’t think the grid
is require for this task. The easiest way I see how this should be solved – using good old JavaScript (+jQuery) and flex
. Although the right way will be resize all elements in a single row, not only nearest siblings of a hovered element. Try it on any screen size.
$(document).ready(function() {
/* defines main digits */
let boxWidth = $('#box').innerWidth();
let itemOuterWidth = $('.item').outerWidth(true);
let itemInnerWidth = $('.item').innerWidth();
SetSeparators(boxWidth, itemOuterWidth);
/* refresh main digits ater page resize */
$(window).resize(function() {
$('.item').css({
"flex": ""
});
boxWidth = $('#box').innerWidth();
itemOuterWidth = $('.item').outerWidth(true);
itemInnerWidth = $('.item').innerWidth();
SetSeparators(boxWidth, itemOuterWidth);
});
$('#box').on('mouseover', '.item', function(e) {
GetElementsPosition($(this).index('.item'), $(this), boxWidth, itemOuterWidth, itemInnerWidth);
});
$('#box').on('mouseleave', '.item', function(e) {
$('.item').css({
"flex": ""
});
});
});
/* set separator elemet to avoid blocks to jump from row to row while resizing */
function SetSeparators(boxWidth, itemOuterWidth) {
$('.separator').remove();
let countRowItems = Math.floor(boxWidth / itemOuterWidth);
$('<div class="separator"></div>').insertBefore('.item:nth-child(' + countRowItems + 'n+1)');
}
function GetElementsPosition(index, element, boxWidth, itemOuterWidth, itemInnerWidth) {
/* calculating row items, column position and row position of a current elemet */
let countRowItems = Math.floor(boxWidth / itemOuterWidth);
let colPosition = index % countRowItems;
let rowPosition = Math.floor(index / countRowItems);
/* exmanpd size of a hovered element in pixels*/
let expandSize = 50;
/* counting number of items in a hovered row */
let currentRowCounter = 0;
$('.item').each(function(e) {
let thisIndex = $(this).index('.item');
let thisRowPosition = Math.floor(thisIndex / countRowItems);
if (rowPosition == thisRowPosition) {
currentRowCounter++;
}
});
/* settting each element widht according to it's position in a list and row */
$('.item').each(function(e) {
$(this).css({
"flex": "0 1 " + itemInnerWidth + "px"
});
let thisIndex = $(this).index('.item');
let thisColPosition = thisIndex % countRowItems;
let thisRowPosition = Math.floor(thisIndex / countRowItems);
if ((rowPosition == thisRowPosition) && (colPosition == thisColPosition)) {
$(this).css({
"flex": "0 1 " + (itemInnerWidth + expandSize) + "px"
});
} else if (rowPosition == thisRowPosition) {
$(this).css({
"flex": "0 1 " + (itemInnerWidth - (expandSize / (currentRowCounter - 1))) + "px"
});
} else {
$(this).css({
"flex": ""
});
}
});
}
* {
box-sizing: border-box;
}
html {
height: 100%;
}
body {
min-height: 100%;
margin: 0;
padding: 0;
}
#box {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: flex-start;
}
.item {
background: gray;
flex: 0 1 250px;
height: 50px;
transition: all .5s ease;
margin: 0 15px 15px 15px;
}
.separator {
flex: 0 1 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='box'>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
</div>