How to apply description over image using CSS Grid?
I am trying to create a grid of images that display descriptions over a faded version of an image when the user hovers over a specified image. My current progress can be seen below and on this JSFiddle .
div#grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 25px;
width: 95%;
margin: 15px auto;
div {
margin: auto;
overflow: hidden;
// cursor: pointer;
background-color: black;
color: white;
img {
height: auto;
max-width: 100%;
}
p {
display: none;
position: relative;
padding: 0;
top: -40px;
left: 10px;
margin: 0;
}
&:hover {
img {
opacity: 0.35;
}
p {
display: block;
}
}
}
}
<h2>Grid Test</h2>
<div id="grid-container">
<div class="">
<img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
<p>A beautiful rock structure.</p>
</div>
<div class="">
<img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
<p>A beautiful rock structure.</p>
</div>
<div class="">
<img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
<p>A beautiful rock structure.</p>
</div>
<div class="">
<img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
<p>A beautiful rock structure.</p>
</div>
<div class="">
<img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
<p>A beautiful rock structure.</p>
</div>
<div class="">
<img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
<p>A beautiful rock structure.</p>
</div>
<div class="">
<img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
<p>A beautiful rock structure.</p>
</div>
<div class="">
<img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
<p>A beautiful rock structure.</p>
</div>
</div>
As you can see in my JSFiddle example, what I am currently doing has these nasty black bars as well as a resizing issue due to relative placement. I can get rid of the relative black bar with margin-bottom
, but it still doesn't fix my unnecessary resizing problem.
Ideally, I would like to have a kiss div
over the image so that I can position things inside that div, but I have no idea how I can get around this without a complete mess. I would like some help on how I can logically do this with the following constraints:
- I would rather not use JavaScript, but I am not 100% against it. But of course there is no framework.
- I don't want to make pictures of
background-image
mydiv
s. - Images must be changed. (although it might be worth noting that the initial size of the images is known)
source to share
There are two reasons for the problem.
Problem # 1: position: relative
The paragraph element is relatively positioned above the image.
div#grid-container div p {
display: none;
position: relative;
padding: 0;
top: -40px;
left: 10px;
margin: 0;
}
The problem is that relative positioning does not remove the element from the normal flow. So even if you use top
and left
to place the text, the original space for the element remains in place ( full explanation ).
You need to remove the item from the normal flow so that it doesn't take up space in the container. Use position: absolute
and create a parent bounding rectangle with position: relative
.
div {
margin: auto;
overflow: hidden;
background-color: black;
color: white;
position: relative; /* new */
p {
display: none;
position: absolute; /* adjusted */
padding: 0;
bottom: 40px; /* adjusted */
left: 10px;
margin: 0;
}
Problem # 2: vertical-align: baseline
Image elements are elements of grid elements. This means that they do not participate in the layout of the grid. They exist in a block layout where line-level elements are automatically assigned a baseline alignment with the vertical-align
( source ) property .
This is why there is a small gap under the images ( full explanation ).
To fix the problem, override the default with vertical-align: top
.
img {
height: auto;
max-width: 100%;
vertical-align: top; /* new */
}
source to share
What you can do is use the :after
on property div
to place a semi-transparent dark background over the image and take advantage of the use position: absolute;
of the paragraph element. See below and this updated demo on the JSFiddle. Read more :after
on MDN .
div {
margin: auto;
overflow: hidden;
// cursor: pointer;
color: white;
position: relative;
img {
display: block;
height: auto;
max-width: 100%;
}
&:hover:after {
position: absolute;
display: block;
content: '';
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(0,0,0,.25);
}
p {
display: none;
position: absolute;
padding: 0;
bottom: 10px;
left: 10px;
margin: 0;
z-index: 1;
}
source to share
You have to remove the background color in the div and place it at p, and set the display to a block at p with opacity 0, hover over the opacity to 0.65 and add padding to the left p and reduce the top border of the box:
div#grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 25px;
width: 95%;
margin: 15px auto;
div {
margin: auto;
overflow: hidden;
// cursor: pointer;
color: white;
img {
height: auto;
max-width: 100%;
}
p {
opacity: 0;
position: relative;
padding: 0;
top: -20px;
left: 0px;
margin: 0;
padding-left: 10px;
background-color: black;
}
&:hover {
img {
opacity: 0.35;
}
p {
opacity: 0.65;
}
}
}
}
You can even play with the opacity of the image, I would put at least 0.75
source to share