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>