I'm trying to make a circle-shaped image with an overlay that shows on hover. However, the "hitbox" of hovering (and clicking) is incorrect, as shown in the snippet below.
This issue seems to only occur in Chrome (not sure about Safari). I've found some fixes on the Internet, but none of them worked. JSFiddle for testing
$(document).ready(function() {
$(".circle").click(function() {
alert($(this).attr("id"));
});
});
#canvas {
width: 100%;
padding-bottom: 75%;
position: relative;
overflow: hidden;
background-color: #eee;
}
.circle {
position: absolute;
width: 25%;
padding-bottom: 25%;
border-radius: 50%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
overflow: hidden;
cursor: pointer;
/*https://stackoverflow.com/a/32987370/5532169*/
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
/*https://stackoverflow.com/a/25206004/5532169*/
z-index: 1;
/*https://stackoverflow.com/a/10296258/5532169*/
-webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);
/*https://stackoverflow.com/a/16878347/5532169*/
-webkit-mask-image: -webkit-radial-gradient(circle, white, black);
}
.mid {
width: 100%;
height: 100%;
position: absolute;
}
.inner {
width: 100%;
height: 100%;
position: relative;
}
.inner>* {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 100%;
height: 100%;
}
.hover {
background-color: rgba(255, 255, 255, 0.6);
opacity: 0;
transition: opacity 0.5s;
}
.hover:hover {
opacity: 100;
transition: opacity 0.5s;
}
span {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 72%;
text-align: center;
font-family: monospace;
font-size: 2em;
font-weight: bold;
color: #08f;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="canvas">
<div id="div1" class="circle">
<div class="mid">
<div class="inner">
<img src="https://dummyimage.com/320x320/000/fff" alt="">
<div class="hover">
<span>Hello World!</span>
</div>
</div>
</div>
</div>
</div>
Edit: Tested in Firefox 57, works without problem. IE and Edge were tested already, so it's a Chrome-/webkit-specific issue.
The blocks in HTML are square defined by position (x, y) and size (width, height) so the browser can have a simplified idea of what is on the page and interact with. So even with border-radius, mask-image, etc... your .circle div is still a square with coming drawn within.
To avoid that, you can't use a dynamic selector like :hover because it will use the shape of the div and that is a square. You need to use javascript to detect mouse position when hovering your block and with that execute an animation (with sinus and cosinus calculation).
You can get the mouse position with something like this :
<div class="circle" onmouseover="hoverFunction(e)"></div>
<script>
function hoverFunction(e) {
var x = e.clientX;
var y = e.clientY;
}
</script>
I also found this topic talking about getting elements position on the page.
You can change only .circle class these properties:
width: 26%;
padding-bottom: 26%;
border-radius: 50%;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
Related
I have an image with a CSS overlay that slides up from the bottom, and it's on the left. I want it in the center. Also, I hate to admit it, but the other post doesn't help. I got a post suggestion(IDK why), but I don't see how it helps me. I'm not super familiar with this and what I'm doing is for a project in a class of mine, which is late, and I'm trying to shoot for extra credit.
I just want to know how to make it go to the center. I have tried moving it to the left by 25, 50, and 75%, same with the right. It just won't move. Here is the code:
.container {
position: relative;
width: 50%;
}
.image {
display: block;
width: 50%;
height: auto;
}
/* This is what I have been using with to move it. */
.overlay {
position: absolute;
bottom: 0;
left: 0;
/* This will move wherever */
right: 0;
background-color: darkblue;
overflow: hidden;
width: 50%;
height: 0;
transition: .5s ease;
}
.container:hover .overlay {
height: 100%;
}
.text {
white-space: nowrap;
color: red;
font-size: 20px;
font-family: cursive;
position: absolute;
overflow: hidden;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
}
<div class="container">
<img src="image is here" alt="Avatar" class="image"> This won't move
<div class="overlay">
<div class="text"><u>This is just here atm</u></div>
</div>
</div>
I solved it. I just needed to use the "center" tag and put my style tag in it. Moved the overlay and it was fixed.
I want to place an overlay on my rounded image but when I set it, the overlay doesn't display over the image correctly? It is filling the column div. Not the overlay container. Can the overlay container be made to size to the image inside of it? I have tried display:inline-block;but that doesn't work. I am using Bootstrap.
HTML Code
<div class="row" style="background-color:#ECECEC">
<div class="col-md-4 col-sm-4" >
<div class="overlaycontainer">
<img class="roundimg" src="images/george1x1.jpg" >
<div class="overlay">
<div class="overlaytext">Hello World</div>
</div>
</div>
<center><h3>George Jones <br><small>Owner and Founder</small></h3></center>
</div>
CSS
.overlay{
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
height: 100%;
width: 100%;
opacity: 0;
transition: .5s ease;
background-color: #008CBA;
border-radius: 50%;
display:inline-block
}
.overlaycontainer{
display:inline-block
}
.overlaycontainer:hover .overlay{
opacity: 1;
}
.overlaytext{
color: white;
font-size: 20px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
}
.roundimg{
max-width: 75%;
height: auto;
border-radius: 50%;
padding-top:10px;
display: block;
margin: 0 auto;
}
Any help would be appreciated.
Thanks
Joe
I was able to get this working a bit better by making this working demo with a placeholder image I was able to link to.
http://codepen.io/anon/pen/ryYaWx?editors=1100
and then adding position: relative to the .overlaycontainer selector, like this:
.overlaycontainer {
display: inline-block;
position: relative; /* <-- this was added*/
}
This works because you have .overlay set to position: absolute and you want the absolute positioning to be relative to .overlaycontainer instead of the entire page. Adding this line will do that.
I have two identical elements. The top one, I'm scaling to double the size and then centering over the normal-sized one. I want its inner element to then be scaled back down to normal size and placed exactly where the normal sized element's inner element is placed.
This seems to be impossible. There seems to be no logic in the scaling + translation of position.
How would I do this?
https://jsfiddle.net/0urdrvao/
HTML:
<div class="top">
<div class="inner">
Inner
</div>
</div>
<div class="bottom">
<div class="inner">
Inner
</div>
</div>
CSS:
body, html
{
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
}
.top,
.bottom
{
position: relative;
top: 0px;
left: 0px;
width: 300px;
height: 300px;
background-color: gray;
z-index: 0;
}
.top
{
position: fixed;
transform-origin: 0 0 0;
transform: translate(-150px, -150px) scale(2);
opacity: .5;
z-index: 1;
}
.inner
{
position: relative;
top: 20vh;
left: 0px;
width: 100px;
height: 40px;
background-color: red;
}
.top .inner
{
/* This doesn't work */
transform: translate(150px,150px) scale(.5);
/* This also doesn't work (doing half)*/
/*transform: translate(75px,75px) scale(.5);*/
/* This also doesn't work (doing double)*/
/*transform: translate(300px,300px) scale(.5);*/
transoform-origin: 0 0 0;
background-color: yellow;
}
Since the top: 20vh will be scaled times 2, the transform-origin should be 0 -20vh.
When reverse a scale/translate you need to go backwards and start with scale and then the translate
.top{
position: fixed;
transform-origin: 0 0;
transform: translate(-150px, -150px) scale(2);
opacity: .5;
z-index: 1;
}
.top .inner{
transform: scale(.5) translate(150px, 150px);
transform-origin: 0 -20vh;
background-color: yellow;
}
Updated fiddle
Or one could do like this, setting origin to 0 0 and transform: scale(.5) translate(150px,150px) translateY(-20vh);
Updated fiddle
I'm scaling a div up with the transform property, but I want to keep its children (which have 1px width or height) the same size. I counter-scaled them by .5, with the expected result that an element of 1px scaled by 2, and then .5, should end up back at 1px, but they wind up a blurry 2px.
Here's the box before scaling it:
.container {
width: 200px;
height: 200px;
margin: 100px;
background-color: #EEE;
position: absolute;
}
.outline {
position: absolute;
background: #1899ef;
z-index: 999999;
opacity: 1 !important;
}
.outlineBottom, .outlineTop {
width: 100%;
height: 1px;
}
.outlineLeft, .outlineRight {
height: 100%;
width: 1px;
}
.outlineRight {
right: 0px;
}
.outlineBottom {
bottom: 0px;
}
<div class="container">
<div class="outline outlineTop"></div>
<div class="outline outlineRight"></div>
<div class="outline outlineBottom"></div>
<div class="outline outlineLeft"></div>
</div>
As you can see, the elements at the edges are a clear, dark 1px blue. Here's what the box looks like after scaling, though:
.container {
width: 200px;
height: 200px;
margin: 100px;
background-color: #EEE;
position: absolute;
transform: scale(2);
}
.outline {
position: absolute;
background: #1899ef;
z-index: 999999;
opacity: 1 !important;
transform: scale(.5);
}
.outlineBottom, .outlineTop {
width: 100%;
height: 1px;
transform: scale(1,.5);
}
.outlineLeft, .outlineRight {
height: 100%;
width: 1px;
transform: scale(.5,1);
}
.outlineRight {
right: 0px;
}
.outlineBottom {
bottom: 0px;
}
<div class="container">
<div class="outline outlineTop"></div>
<div class="outline outlineRight"></div>
<div class="outline outlineBottom"></div>
<div class="outline outlineLeft"></div>
</div>
And here's a post-scaled render from Chrome 41.0.2272.89 Mac, which is what I'm running.
Adding transform-3d(0, 0, 0) didn't appear to help. A solution was found using the zoom property, but since zoom isn't well supported I'd like to avoid that. Adding filter: blur(0px); didn't appear to have any effect either.
It was posited in chat that perhaps the children are first scaled to .5 and then doubled in size, causing them to be scaled down to .5px and then back up from there. Is there any way to ensure the order that they're rendered in causes them to first be scaled up to 2px and then halved? Against my better judgement, I tried forcing the render order with JS, but unsurprisingly, that didn't have any effect (though, interestingly, the bottom element did maintain its original color).
Failing that, are there any other solutions floating around out there? I can't be the only one who's run into this problem.
It is to do with the default transform-origin on the scaled elements. It defaults to 50% 50% for any element being transformed, but this has issues when scaling down 1px values as it has to centre the scale on a half pixel and the rendering of the elements has issues from here on out. You can see it working here with the transform-origin moved to the relevant extremes for each item.
A bit of playing about shows that this same blurring happens on scaled elements for any dimension where the scaling ends up halving a pixel.
body {
padding: 1em;
}
.container {
width: 200px;
height: 200px;
margin: 100px;
background-color: #EEE;
position: absolute;
transform: scale(2);
}
.outline {
position: absolute;
background: #1899ef;
z-index: 999999;
opacity: 1 !important;
}
.outlineBottom, .outlineTop {
width: 100%;
height: 1px;
transform: scale(1, 0.5);
}
.outlineBottom {
bottom: 0;
transform-origin: 0 100%;
}
.outlineTop {
transform-origin: 0 0;
}
.outlineLeft, .outlineRight {
height: 100%;
width: 1px;
transform: scale(.5,1);
}
.outlineRight {
right: 0px;
transform-origin: 100% 0;
}
.outlineLeft {
left: 0px;
transform-origin: 0 0;
}
<div class="container">
<div class="outline outlineTop"></div>
<div class="outline outlineRight"></div>
<div class="outline outlineBottom"></div>
<div class="outline outlineLeft"></div>
</div>
I am trying to achieve something like this:
When I hover over an image, I would like to put on that image this dark color with some text and the icon.
I am stuck here. I found some tutorials but they didn't work out for this case.
Also, another issue -- every image has a different height. The width is always the same.
How can this effect be achieved?
You can achieve this with this simple CSS/HTML:
.image-container {
position: relative;
width: 200px;
height: 300px;
}
.image-container .after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: none;
color: #FFF;
}
.image-container:hover .after {
display: block;
background: rgba(0, 0, 0, .6);
}
HTML
<div class="image-container">
<img src="http://lorempixel.com/300/200" />
<div class="after">This is some content</div>
</div>
Demo: http://jsfiddle.net/6Mt3Q/
UPD: Here is one nice final demo with some extra stylings.
.image-container {
position: relative;
display: inline-block;
}
.image-container img {display: block;}
.image-container .after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: none;
color: #FFF;
}
.image-container:hover .after {
display: block;
background: rgba(0, 0, 0, .6);
}
.image-container .after .content {
position: absolute;
bottom: 0;
font-family: Arial;
text-align: center;
width: 100%;
box-sizing: border-box;
padding: 5px;
}
.image-container .after .zoom {
color: #DDD;
font-size: 48px;
position: absolute;
top: 50%;
left: 50%;
margin: -30px 0 0 -19px;
height: 50px;
width: 45px;
cursor: pointer;
}
.image-container .after .zoom:hover {
color: #FFF;
}
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" rel="stylesheet"/>
<div class="image-container">
<img src="http://lorempixel.com/300/180" />
<div class="after">
<span class="content">This is some content. It can be long and span several lines.</span>
<span class="zoom">
<i class="fa fa-search"></i>
</span>
</div>
</div>
You could use a pseudo element for this, and have your image on a hover:
.image {
position: relative;
height: 300px;
width: 300px;
background: url(http://lorempixel.com/300/300);
}
.image:before {
content: "";
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
transition: all 0.8s;
opacity: 0;
background: url(http://lorempixel.com/300/200);
background-size: 100% 100%;
}
.image:hover:before {
opacity: 0.8;
}
<div class="image"></div>
Putting this answer here as it is the top result in Google.
If you want a quick and simple way:
filter: brightness(0.2);
*Not compatible with IE
A bit late for this, but this thread comes up in Google as a top result when searching for an overlay method.
You could simply use a background-blend-mode
.foo {
background-image: url(images/image1.png), url(images/image2.png);
background-color: violet;
background-blend-mode: screen multiply;
}
What this does is it takes the second image, and it blends it with the background colour by using the multiply blend mode, and then it blends the first image with the second image and the background colour by using the screen blend mode. There are 16 different blend modes that you could use to achieve any overlay.
multiply, screen, overlay, darken, lighten, color-dodge, color-burn, hard-light, soft-light, difference, exclusion, hue, saturation, color and luminosity.
.bg-img{
text-align: center;
padding: 130px 0px;
width: 100% !important;
background-size: cover !important;
background-repeat: no-repeat !important;
background: linear-gradient(0deg, rgba(0, 0, 0, 0.86), rgba(0, 0, 0, 0.86)), url(your-img-path);
}