In a grid, I want to highlight group of cells - a rectangle shape - starting from top left cell up to the cell under the mouse position.
Let's say our grid initially looks like this:
.grid {
display: grid;
grid-template-columns: repeat(5, 50px);
grid-template-rows: repeat(5, 50px);
gap: 5px;
}
.grid-item {
display: flex;
justify-content: center;
align-items: center;
background: lightgray;
}
<div class="grid">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
<div class="grid-item">9</div>
<div class="grid-item">10</div>
<div class="grid-item">11</div>
<div class="grid-item">12</div>
<div class="grid-item">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item">16</div>
<div class="grid-item">17</div>
<div class="grid-item">18</div>
<div class="grid-item">19</div>
<div class="grid-item">20</div>
<div class="grid-item">21</div>
<div class="grid-item">22</div>
<div class="grid-item">23</div>
<div class="grid-item">24</div>
<div class="grid-item">25</div>
</div>
And now the user hovers with the mouse over cell number 18. The grid should look like this now:
.grid {
display: grid;
grid-template-columns: repeat(5, 50px);
grid-template-rows: repeat(5, 50px);
gap: 5px;
}
.grid-item {
display: flex;
justify-content: center;
align-items: center;
background: lightgray;
}
.grid-item-blue {
background: lightblue;
}
<div class="grid">
<div class="grid-item grid-item-blue">1</div>
<div class="grid-item grid-item-blue">2</div>
<div class="grid-item grid-item-blue">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item grid-item-blue">6</div>
<div class="grid-item grid-item-blue">7</div>
<div class="grid-item grid-item-blue">8</div>
<div class="grid-item">9</div>
<div class="grid-item">10</div>
<div class="grid-item grid-item-blue">11</div>
<div class="grid-item grid-item-blue">12</div>
<div class="grid-item grid-item-blue">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item grid-item-blue">16</div>
<div class="grid-item grid-item-blue">17</div>
<div class="grid-item grid-item-blue">18</div>
<div class="grid-item">19</div>
<div class="grid-item">20</div>
<div class="grid-item">21</div>
<div class="grid-item">22</div>
<div class="grid-item">23</div>
<div class="grid-item">24</div>
<div class="grid-item">25</div>
</div>
I prefer css solution. Is is possible using css only? If not, how would you do this in JS?
Here's a pure css Idea if you don't mind nesting the content on more level just to put it over the fake background.
.grid {
overflow:hidden;
display: grid;
grid-template-columns: repeat(5, 50px);
grid-template-rows: repeat(5, 50px);
gap: 5px;
}
.grid-item {
background: lightgray;
position: relative;
display: flex;
}
.grid-item>span {
z-index: 2;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.grid-item:hover:before {
position: absolute;
content: '';
background: linear-gradient(to left,#ff000000 0px 50px,#ffffff 50px 55px) 0 0/55px, linear-gradient(to top,lightblue 0px 50px,#ffffff00 50px 55px) 0 0/1px 55px ;
z-index: 1;
width: calc(55px * 9);
height: calc(55px * 9);
bottom: 0;
right: 0;
}
<div class="grid">
<div class="grid-item"><span>1</span></div>
<div class="grid-item"><span>2</span></div>
<div class="grid-item"><span>3</span></div>
<div class="grid-item"><span>4</span></div>
<div class="grid-item"><span>5</span></div>
<div class="grid-item"><span>6</span></div>
<div class="grid-item"><span>7</span></div>
<div class="grid-item"><span>8</span></div>
<div class="grid-item"><span>9</span></div>
<div class="grid-item"><span>10</span></div>
<div class="grid-item"><span>11</span></div>
<div class="grid-item"><span>12</span></div>
<div class="grid-item"><span>13</span></div>
<div class="grid-item"><span>14</span></div>
<div class="grid-item"><span>15</span></div>
<div class="grid-item"><span>16</span></div>
<div class="grid-item"><span>17</span></div>
<div class="grid-item"><span>18</span></div>
<div class="grid-item"><span>19</span></div>
<div class="grid-item"><span>20</span></div>
<div class="grid-item"><span>21</span></div>
<div class="grid-item"><span>22</span></div>
<div class="grid-item"><span>23</span></div>
<div class="grid-item"><span>24</span></div>
<div class="grid-item"><span>25</span></div>
</div>
Here is pure CSS solution with flexbox but too complex.
.grid {
display: flex;
flex-wrap: wrap;
flex-flow: wrap-reverse;
direction: rtl;
width: calc(50px*5 + 5px*4);
}
.grid-item {
width: 50px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
background: lightgray;
margin-bottom: 5px;
}
.grid-item:not(:nth-child(5n + 1)) {
margin-right: 5px;
}
.grid-item:nth-child(5n - 4):hover,
.grid-item:nth-child(5n - 4):hover~.grid-item,
.grid-item:nth-child(5n - 3):hover,
.grid-item:nth-child(5n - 3):hover~.grid-item:not(:nth-child(5n + 1)),
.grid-item:nth-child(5n - 2):hover,
.grid-item:nth-child(5n - 2):hover~.grid-item:not(:nth-child(5n + 1)):not(:nth-child(5n + 2)),
.grid-item:nth-child(5n - 1):hover,
.grid-item:nth-child(5n - 1):hover~.grid-item:not(:nth-child(5n + 1)):not(:nth-child(5n + 2)):not(:nth-child(5n + 3)),
.grid-item:nth-child(5n):hover,
.grid-item:nth-child(5n):hover~.grid-item:not(:nth-child(5n + 1)):not(:nth-child(5n + 2)):not(:nth-child(5n + 3)):not(:nth-child(5n + 4))
{
background: lightblue;
}
<div class="grid">
<div class="grid-item">25</div>
<div class="grid-item">24</div>
<div class="grid-item">23</div>
<div class="grid-item">22</div>
<div class="grid-item">21</div>
<div class="grid-item">20</div>
<div class="grid-item">19</div>
<div class="grid-item">18</div>
<div class="grid-item">17</div>
<div class="grid-item">16</div>
<div class="grid-item">15</div>
<div class="grid-item">14</div>
<div class="grid-item">13</div>
<div class="grid-item">12</div>
<div class="grid-item">11</div>
<div class="grid-item">10</div>
<div class="grid-item">9</div>
<div class="grid-item">8</div>
<div class="grid-item">7</div>
<div class="grid-item">6</div>
<div class="grid-item">5</div>
<div class="grid-item">4</div>
<div class="grid-item">3</div>
<div class="grid-item">2</div>
<div class="grid-item">1</div>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With