11

It is well known that using max-height and max-width can make an image auto fit in a div, like the following:

.cover img {
    max-width: 100%;
    max-height: 100%;
}

Is there a way to make a translucent cover (by setting opacity: 0.8 to a div) that just fit the size of the image without getting the width and height by javascript?

The following is my attempt in jsfiddle. I can only make it cover the whole container, but what I want is just to cover the image only. The size of the image is variable as they are to be uploaded by user. https://jsfiddle.net/muorou0c/1/

vals
  • 61,425
  • 11
  • 89
  • 138
cytsunny
  • 4,838
  • 15
  • 62
  • 129

6 Answers6

6

Here's a simple flexbox-solution that should be quite straight forward:

.container {
  display: block;
  height: 300px;
  width: 300px;
  background-color: #000;
  border: 2px solid red;
  display: flex;
  align-items: center;
  justify-content: center;
}
.inner {
  position: relative;
}
.container img {
  max-width: 300px;
  max-height: 300px;
  display: block;
}
.cover {
  display: none;
}
.container:hover .cover{
  display: block;
  position: absolute;
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
  background-color: #FFF;
  opacity: 0.8;
}
<div class="container">
  <div class="inner">
    <img src="http://lorempixel.com/400/200/">
    <div class="cover"></div>
  </div>
</div>

<div class="container">
  <div class="inner">
    <img src="http://lorempixel.com/400/800/">
    <div class="cover"></div>
  </div>
</div>

There are three parts that makes this solution work:

  1. Hard coded container size on img tag (as max-width: 300px, max-height: 300px), to maintain aspect ratio and size.
  2. Using an inner container div that wraps the boundaries for the cover layer, setting the boundary as to how big the cover can be. The .cover could be replaced with a ::before or ::after pseudo element, see the alternative fiddle below.
  3. Using flexbox to center the inner container in the outer container. This could also be done using the position absolute + translate3d trick used to position the .cover element in the original question, see the alternative fiddle below.

Here's a fiddle with the alternative solutions from point 2 & 3 above: https://jsfiddle.net/muorou0c/18/

Johan Persson
  • 1,875
  • 11
  • 11
3

I have adapted your fiddle, and added an extra layer under container

.container {
  position: relative;
  display: block;
  height: 300px;
  width: 300px;
  max-height: 300px;
  max-width: 300px;
  background-color: #000;
  border: 2px solid red;
}

.container2 {
  max-width: inherit;
  max-height: inherit;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
  border: 2px solid cyan;
}

.container2 img {
  max-height: inherit;
  max-width: inherit;
}

.cover {
  display: none;
}
.container:hover .cover{
  display: block;
  position: absolute;
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
  background-color: #FFF;
  opacity: 0.8;
}
<div class="container">
  <div class="container2">
  <img src="http://lorempixel.com/400/200/">
      <div class="cover"></div>
  </div>
</div>

<div class="container">
  <div class="container2">
  <img src="http://lorempixel.com/400/800/">
  <div class="cover"></div>
  </div>
</div>

This works by setting to container a max-height ans max-width. This go to the image via inherit values.

Then the image gets its dimension.

And the container2 element gets it's dimension from the child.

and finally cover uses the dimension from container2

vals
  • 61,425
  • 11
  • 89
  • 138
2

If it fits your needs, there are a lot of filters you can add over you image(rather than covering it with a colored div). Here's a example.

img:hover{
  -webkit-filter:  brightness(200%); 
  filter:  brightness(200%);
}
miraco
  • 298
  • 5
  • 10
  • Good idea, but for my actual use, I also need to add a edit button on the cover, so not suitable for my case. – cytsunny Dec 24 '15 at 08:27
  • I'd assume you want your buttons to be on the same place(relative to the container), no matter the image size. In this case you can combine your original solution with mine. – miraco Dec 24 '15 at 08:32
2

.container {
  position: relative;
  display: block;
  height: 300px;
  width: 300px;
  background-color: #000;
  border: 2px solid red;
}
.container img {
    position: absolute;
    display: block;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%);
    object-fit: cover;
    object-position: center;
    height: 100%;
    width: 100%;
}
.cover {
  display: none;
}
.container:hover .cover{
  display: block;
  position: absolute;
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
  background-color: #FFF;
  opacity: 0.8;
}
<div class="container">
  <img src="http://lorempixel.com/400/200/">
  <div class="cover"></div>
  </div>
</div>

<div class="container">
  <img src="http://lorempixel.com/400/800/">
  <div class="cover"></div>
</div>
Amir Naeem
  • 570
  • 6
  • 23
1

Ok I made some modification to the way your code was organised.

.container {
  position: relative;
  display: block;
  height: 300px;
  width: 300px;
  background-color: #000;
  border: 2px solid red;
}
.image {
  display: block;
  content: "";
  width:auto;
  position: relative;
  max-width: 100%;
  max-height: 100%;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
  background-image: url("http://lorempixel.com/400/200/");
}
.image:hover:after{
  display:block;
  content: "";
  position: absolute;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: #fff;
  opacity: .5; /* if needed */
}
<div class="container">
  <div class="image">
     <img src="http://lorempixel.com/400/200/" style="visibility:hidden"/>
  </div>
</div>

The time when you are constructing your html add the img element for maintaining the height of the container using javascript. I think in case of an uploaded image scenario the html must be constructed dynamically.

references

Overlay image on dynamically sized div

How to get div height to auto-adjust to background size?

Why don't :before and :after pseudo elements work with `img` elements?

Community
  • 1
  • 1
harshitpthk
  • 4,058
  • 2
  • 24
  • 32
1

Sounds like a job for a pseudo element.

.container{
     background:yellow;
     border:2px solid red;
     width:300px;
     height:300px;
     text-align:center;
}

.container:before{ 
    content: "";
    display: inline-block;
    vertical-align: middle;
    height: 100%;
  }

.cover{
        position:relative;
        display:inline-block;
        vertical-align:middle;
    }
    
 .cover:hover:after{
        content:"";
        position:absolute;
        top:0;
        left:0;
        right:0;
        bottom:0;
        max-width:inherit;
        max-height:inherit;
        opacity:.5;
        background:blue;
    }

.container img{
    display:block;
    max-width:300px;
    max-height:300px;
}
<div class="container"><div class="cover"><img src="http://lorempixel.com/400/200/"/></div></div>

Just assign the background property to the .cover:after selector to get the overlay.

Donnie D'Amato
  • 3,832
  • 1
  • 15
  • 40
  • This is not a working solution. You should test before you answer, especially I have already givent the basic code on jsfiddle. https://jsfiddle.net/f3w8hura/ – cytsunny Dec 28 '15 at 04:06
  • Then I think you didn't read the question carefully. What I want is a cover on the auto-scale image inside a container. Your snippet don't even contain an image. – cytsunny Dec 28 '15 at 04:11
  • 1
    What my answer is trying to explain is that the pseudo element will take up the dimensions of the parent (in this example the div tag; in the case you want, the img tag). I've explicitly sent the dimensions of the div here as an example, but the img tag will inherit its own dimensions. – Donnie D'Amato Dec 28 '15 at 04:16
  • Seems like you still don't understand what I am asking. Take a look at humblebee's answer. He is doing the right thing, although he is not able to do that with CSS only. – cytsunny Dec 28 '15 at 08:35
  • 1
    One more edit. If this isn't what you want, I'll never understand. – Donnie D'Amato Dec 28 '15 at 09:32