Reputation: 553
This a table that created with CSS Grid Layout, but I have a problem with it, I can't make hover state on each row.
I only want use CSS for this.
Can anyone give me a solution for this?
.table {
display: grid;
grid-template-columns: [col-start] auto [col-end];
grid-template-rows: [header-start] 50px [header-end row-start] auto [row-end];
grid-auto-rows: auto;
grid-auto-columns: auto;
grid-gap: 1px;
}
.table>* {
background: gray;
padding: 10px;
}
.heading {
background: navy;
color: #fff;
grid-row: header;
}
<div class="table">
<div class="heading">Title 1</div>
<div class="heading">Title 2</div>
<div class="heading">Title 3</div>
<div class="heading">Title 4</div>
<div class="heading">Title 5</div>
<div class="row">Row 1</div>
<div class="row">Row 1</div>
<div class="row">Row 1</div>
<div class="row">Row 1</div>
<div class="row">Row 1</div>
<div class="row">Row 2</div>
<div class="row">Row 2</div>
<div class="row">Row 2</div>
<div class="row">Row 2</div>
<div class="row">Row 2</div>
<div class="row">Row 3</div>
<div class="row">Row 3</div>
<div class="row">Row 3</div>
<div class="row">Row 3</div>
<div class="row">Row 3</div>
</div>
Upvotes: 53
Views: 30282
Reputation: 11
I have solution for your problem. The example below:
.grid .row {
display: grid;
grid-template-columns: repeat(4, 1fr);
border-bottom: 1px solid gray;
}
.grid .row div {
padding: 10px;
display: flex;
align-items: center;
}
.grid .row:last-child {
border: none;
}
.grid .row:hover {
background-color: #cccccc;
transition: .2s all;
}
<div class='grid'>
<div class='row'>
<div>Header</div>
<div>Header</div>
<div>Header</div>
<div>Header</div>
</div>
<div class='row'>
<div>Content</div>
<div>Content</div>
<div>Content</div>
<div>Content</div>
</div>
<div class='row'>
<div>Content</div>
<div>Content</div>
<div>Content</div>
<div>Content</div>
</div>
<div class='row'>
<div>Content</div>
<div>Content</div>
<div>Content</div>
<div>Content</div>
</div>
</div>
Upvotes: -2
Reputation: 5432
Now that all big browsers support CSS Subgrids (and nesting), this is a much easier task
.myGrid {
position: relative;
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 10px;
.myRow {
grid-column: span 3;
display: grid;
grid-template-columns: subgrid;
padding: 5px 0;
&:hover {
background-color: #f8f8f8;
}
}
}
<div class="myGrid">
<span>head1</span>
<span>head2</span>
<span>head3</span>
<div class="myRow">
<span>row1 col1</span>
<span>row1 col2</span>
<span>row1 col3</span>
</div>
<div class="myRow">
<span>row2 col1</span>
<span>row2 col2</span>
<span>row2 col3</span>
</div>
<div class="myRow">
<span>row3 col1</span>
<span>row3 col2</span>
<span>row3 col3</span>
</div>
<div class="myRow">
<span>row4 col1</span>
<span>row4 col2</span>
<span>row4 col3</span>
</div>
<div class="myRow">
<span>row5 col1</span>
<span>row5 col2</span>
<span>row5 col3</span>
</div>
<div class="myRow">
<span>row6 col1</span>
<span>row6 col2</span>
<span>row6 col3</span>
</div>
</div>
Upvotes: 1
Reputation: 21072
Nowadays the solution is subgrid. It solves the problem with gaps in the main grid, the markup is somewhat similar to tr
and table
meaning you have nesting:
<div class="my-subgrid-row">
<div class="cell-col1"></div>
<div class="cell-col2"></div>
...
</div>
and CSS is quite straightforward without a lot of hacks.
Upvotes: -1
Reputation: 2249
I ended up with a different solution. My table looked like this:
.table {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
}
<div class="table">
<span>head1</span>
<span>head2</span>
<span>head3</span>
<span>row1 col1</span>
<span>row1 col2</span>
<span>row1 col3</span>
<span>row2 col1</span>
<span>row2 col2</span>
<span>row2 col3</span>
</div>
Now you want the hover state per row. Adding an element wrapping each row breaks the parent grid as it would really be the children of those row wrappers you're trying to lay out in a grid. In addition, I preferred:
<table>
. Which about doubled the number of lines needed and required more styling.nth-child
puzzling.div
, add a class .row
and display: contents
, then with .row:hover > span
as a selector you could add opacity: 0.6
. Seems decent! Some other answers go in this direction.I ended up going for the following which I feel is simpler:
.row {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.row:hover {
opacity: 0.6
}
<div class="row">
<span>head1</span>
<span>head2</span>
<span>head3</span>
</div>
<div class="row">
<span>row1 col1</span>
<span>row1 col2</span>
<span>row1 col3</span>
</div>
<div class="row">
<span>row2 col1</span>
<span>row2 col2</span>
<span>row2 col3</span>
</div>
Upvotes: 1
Reputation: 761
Since you are treating this as a table, where the elements stay in the same row, you can also wrap each row in a DIV with "display" set to "contents." This forms an innocuous parent element that you use for hover, and then style the child elements. (display: contents is not yet supported in Edge, though.)
.table {
display: grid;
grid-template-columns: [col-start] auto [col-end];
grid-template-rows: [header-start] 50px [header-end row-start] auto [row-end];
grid-auto-rows: auto;
grid-auto-columns: auto;
grid-gap: 1px;
overflow: hidden;
background: gray;
}
.table .row, .table .heading{
padding: 10px;
position: relative;
}
.heading {
background: navy;
color: #fff;
grid-row: header;
}
.row span {
position: relative;
z-index: 2;
}
.rowWrapper{
display: contents;
}
.rowWrapper:hover > div{
background-color: orange;
}
<div class="table">
<div class="heading">Title 1</div>
<div class="heading">Title 2</div>
<div class="heading">Title 3</div>
<div class="heading">Title 4</div>
<div class="heading">Title 5</div>
<div class="rowWrapper">
<div class="row"><span>Row 1</span></div>
<div class="row"><span>Row 1</span></div>
<div class="row"><span>Row 1</span></div>
<div class="row"><span>Row 1</span></div>
<div class="row"><span>Row 1</span></div>
</div>
<div class="rowWrapper">
<div class="row"><span>Row 2</span></div>
<div class="row"><span>Row 2</span></div>
<div class="row"><span>Row 2</span></div>
<div class="row"><span>Row 2</span></div>
<div class="row"><span>Row 2</span></div>
</div>
<div class="rowWrapper">
<div class="row"><span>Row 3</span></div>
<div class="row"><span>Row 3</span></div>
<div class="row"><span>Row 3</span></div>
<div class="row"><span>Row 3</span></div>
<div class="row"><span>Row 3</span></div>
</div>
</div>
Upvotes: 76
Reputation: 1631
Here's my solution, based on sibling combinators.
The main part is:
.datacell:hover ~ .datarow {
background-color: rgba(255,255,0,0.5);
}
.datacell:hover ~ .datarow + .datacell ~ .datarow{
background-color: transparent;
}
Snippet:
.datatable{
display:grid;
grid-gap: 0;
grid-template-columns: auto 1fr auto;
position: relative;
}
.datarow{
grid-column: 1 / 4;
z-index: 0;
}
.datacell{
z-index: 1;
padding: 8px;
border-bottom: 1px solid #c0c0c0;
}
.datacell:hover ~ .datarow {
background-color: rgba(255,255,0,0.5);
}
.datacell:hover ~ .datarow + .datacell ~ .datarow{
background-color: transparent;
}
.row-1{ grid-row: 1;}
.row-2{ grid-row: 2;}
.row-3{ grid-row: 3;}
.col-1{ grid-column: 1;}
.col-2{ grid-column: 2;}
.col-3{ grid-column: 3;}
<div class="datatable">
<div class="datacell col-1 row-1">Row 1 Column 1</div>
<div class="datacell col-2 row-1">Row 1 Column 2</div>
<div class="datacell col-3 row-1">Row 1 Column 3</div>
<div class="datarow row-1"></div>
<div class="datacell col-1 row-2">Row 2 Column 1</div>
<div class="datacell col-2 row-2">Row 2 Column 2</div>
<div class="datacell col-3 row-2">Row 2 Column 3</div>
<div class="datarow row-2"></div>
<div class="datacell col-1 row-3">Row 3 Column 1</div>
<div class="datacell col-2 row-3">Row 3 Column 2</div>
<div class="datacell col-3 row-3">Row 3 Column 3</div>
<div class="datarow row-3"></div>
</div>
The html must be structured so that a .datarow
element closes the virtual grid row and spans all the preceding cells. Explicitation of the positioning inside the grid is needed in order to let cells and rows overlap.
Upvotes: 7
Reputation: 273022
Here is a trick using pseudo-element. The idea is to use the element as a background and make it overflow on the left and right so that it will cover all the row. Like that if you hover on any element inside a row you change the color and it's like you changed the color of the whole row.
This trick involve few changes on the markup and also more CSS.
.table {
display: grid;
grid-template-columns: [col-start] auto [col-end];
grid-template-rows: [header-start] 50px [header-end row-start] auto [row-end];
grid-auto-rows: auto;
grid-auto-columns: auto;
grid-gap: 1px;
overflow: hidden;
background: gray;
}
.table>* {
padding: 10px;
position: relative;
}
.heading {
background: navy;
color: #fff;
grid-row: header;
}
.row span {
position: relative;
z-index: 2;
}
.row:before {
content: "";
position: absolute;
top: 0;
bottom: 0;
right: -1000%;
left: -1000%;
z-index: 1;
}
.row:after {
content: "";
position: absolute;
top: 0;
bottom: 0;
right: -1px;
width: 1px;
z-index: 2;
background-color: #fff;
}
.row:nth-child(5n+5)::after {
bottom: -1px;
right: 0;
left: -1000%;
height: 1px;
z-index: 3;
width: auto;
top: auto;
background-color: #fff;
}
.row:hover::before {
background-color: red;
}
<div class="table">
<div class="heading">Title 1</div>
<div class="heading">Title 2</div>
<div class="heading">Title 3</div>
<div class="heading">Title 4</div>
<div class="heading">Title 5</div>
<div class="row"><span>Row 1</span></div>
<div class="row"><span>Row 1</span></div>
<div class="row"><span>Row 1</span></div>
<div class="row"><span>Row 1</span></div>
<div class="row"><span>Row 1</span></div>
<div class="row"><span>Row 2</span></div>
<div class="row"><span>Row 2</span></div>
<div class="row"><span>Row 2</span></div>
<div class="row"><span>Row 2</span></div>
<div class="row"><span>Row 2</span></div>
<div class="row"><span>Row 3</span></div>
<div class="row"><span>Row 3</span></div>
<div class="row"><span>Row 3</span></div>
<div class="row"><span>Row 3</span></div>
<div class="row"><span>Row 3</span></div>
</div>
Upvotes: 19