If an image in an element with a decimal width is animated using css (opacity), the image loads at a fixed pixel width then after completing the transition changes size to the correct decimal pixels.
I have tested this on Chrome only. See the fiddle, which shows the problem only when using css animations. http://jsfiddle.net/minlare/kext0af4/
.opacity{
width: 400px;
}
.opacity div {
width: calc(100% / 3);
float: left;
}
.opacity img{
max-width: 100%;
display: block;
opacity: 1;
transition: .25s;
}
.opacity img.visible{
opacity: 0;
}
Any way around this?
I solved adding outline: 1px transparent solid;
.opacity img{
max-width: 100%;
display: block;
opacity: 1;
transition: .25s;
outline: 1px transparent solid;
}
Fork: http://jsfiddle.net/0dvvd1n1/
Also backface-visibility: hidden; solves the issue but the outline approach doesn't create sharpened edges.
Another method to sort of solve it is to add translate:transformZ(0) This forces GPU rendering, which corrects the jumping in the version I tested it in (Chrome 43.0.2357.132 on Mac). However, it can cause issues if there are a large number of GPU rendered elements that have transitions.
http://jsfiddle.net/kudj7zxn/
.opacity img{
max-width: 100%;
display: block;
opacity: 1;
transition: .25s;
transform: translateZ(0);
}
Related
My goal is to make a circular icon button wherein a single icon is enveloped by a circle, and the circle shrinks on hover, but the icon stays centered.
I got this effect working in Firefox and Chrome, but in Safari 9 (I assume it's similar in Safari 10), when I hover over the buttons, their vertical position occasionally moves up and down unexpectedly. It seems to mostly occur when rapidly changing which button is being hovered.
This is the HTML structure of the button:
<a class='icon-button'>
<button>
<span class='bg'></span>
<span class='icon'>A</span>
</button>
</a>
This is the SCSS code I am applying:
.icon-button {
$width: 2em;
display: inline-block;
width: $width;
height: $width;
overflow: hidden;
cursor: pointer;
button {
position: relative;
display: flex;
align-items: center;
text-align: center;
width: $width;
height: $width;
padding: 0;
margin: 0;
background: none;
border: none;
cursor: pointer;
}
.bg {
background-color: #FF9999;
width: $width;
height: $width;
border-radius: $width / 2;
margin: 0 auto;
transition: width 128ms linear, height 128ms linear;
}
&:hover .bg {
width: 0.8 * $width;
height: 0.8 * $width;
}
.icon {
color: #FFF;
position: absolute;
top: 0;
left: 0;
line-height: $width;
width: 100%;
}
}
Here is a JSFiddle page where I replicated the issue with the relevant code: https://jsfiddle.net/Auroratide/6u463jL5/3/
Does anyone know what is causing this to happen in Safari but not the other browsers? I'm probably going to need to change my strategy so the CSS is not as jank, but I'm curious nonetheless.
UPDATE:
Here a link to a video of what I am seeing, contrasting Firefox with Safari:
http://tarm.wdfiles.com/local--files/files/safari_jankiness.mov
Try adding
-webkit-transition: width 128ms linear, height 128ms linear;
The -webkit- refers to browsers such as Chrome and Safari, so will hopefully fix the problem you're experiencing.
It seems that the below CSS fixes this:
.icon-button {
position: relative;
}
.icon-button button {
position: absolute;
top: 0; left: 0;
}
I'm still not really sure what was going on in Safari, but it seems to have been a positioning issue relative to the size of adjacent elements (I had noticed the issue does not arise on a button in isolation). Absolute positioning guarantees the elements are positioned based solely on the parent, so I'm guessing that's why this fixes the issue.
I'm trying to remove blur effect that is happening during scaling transition. Picture during transition is passable but this font transition is so ugly... Is there any method to fix it? I have tried with "translateY(0) translateZ(0)" but no effect at all. When the effect is done, everything is going back to normal.
.circlee
{
display: inline-block;
margin-right: 50px;
/*margin-top: 200px;*/
width: 200px;
height: 200px;
border-radius: 50%;
border: 2px black solid;
background-image: url(http://lorempixel.com/200/200/);
transition: all 1s ease-in-out;
}
.circlee:hover
{
transform: scale(1.15);
}
<div class="circlee">wwww</div>
<div class="circlee">xxxx</div>
<div class="circlee">ssss</div>
From the looks of it your image is only 200px by 200px . The hover effect is causing the image to stretch which results to quality loss / blur. You can either get a higher quality image so when it stretches it doesn't lose quality for an example ...an image of 210px by 210px with a resolution of 72 pixels . OR you could make your circle 190px by 190px and scale it up to 200px on hover resulting in the exact size of your background image.
OR just change the width and height on hover instead. Example:
.circlee
{
display: inline-block;
margin-right: 50px;
/*margin-top: 200px;*/
width: 190px;
height: 190px;
border-radius: 50%;
border: 2px black solid;
background-image: url(http://lorempixel.com/200/200/);
background-size:100% 100%;
transition: all 1s ease-in-out;
}
.circlee:hover
{
width:200px;
height: 200px;
}
<div class="circlee">wwww</div>
<div class="circlee">xxxx</div>
<div class="circlee">ssss</div>
Works like butter!
Main question
I have two divs, one nested inside the other and i wish to shift inner div outside (upwards) of outer div and slide-in it on a hover.
Markup is looking like so:
<div class="body">
<div class="inner">Green is variable-height text which slides in on viewport hover</div>
Blue is a viewport (<body>, visible part of a page), which content should be compressed upon green slide-in
</div>
And (a little pseudo) css:
.body {
background: #aaf;
height: 300px;
width: 300px;
overflow: hidden;
}
.inner, .body:hover .inner {
-webkit-transition:all linear 0.2s;
transition:all linear 0.2s;
}
.inner {
background: #afa;
width: 300px;
margin-top:-some-magic-to-get-this-div-height;
}
.body:hover .inner {
margin-top: 0;
}
And a final result animation i'd like to get, without using fixed height of green div:
Also, this example (with a guessed and hard-coded height value of 2.5em) on jsfiddle to experiment with:
http://jsfiddle.net/n7vyLoh4/20/
Possible partial work-around (not satisfactory)
It is possible to partially implement what i want, using transitioning max-height instead of transitioning margin-top, the transition of max-height: 0; -> max-height: 100%; with overflow: hidden; set at all times
works, but has two draw-backs:
it doesn't slide in, it's more like drops the curtain
it doesn't stop transition at the end of green div, it transits till the end of outer blue div, which especially noticeable at reverse transition, when it first travels all the way from bottom of blue div to bottom of green div before any effect is visible. Also, this means that despite transition time set to 0.2s, it will spend only fraction of this time on transiting trough green div, because this 100% are 100% of parent div, not inner one (and my question could be answered if there is a way to calculate the 100% of inner div height).
Here is an illustration:
And fiddle for that:
http://jsfiddle.net/bsd7vnwu/1/
This is the pure css solution, which means it does not require any scripts, just a browser that support transitions:
.body {
background: #aaf;
height: 300px;
width: 300px;
overflow: hidden;
}
.inner {
-webkit-transition:all cubic-bezier(0,.81,.4,1) 0.5s;
transition:all cubic-bezier(0,.81,.4,1) 0.5s;
}
.inner {
background: #afa;
width: 300px;
position: absolute;
margin-top: -100%;
float: left;
}
.body:hover .inner {
position: relative;
margin-top: 0;
}
And Fiddle is here
I think this is the effect you want. CSS doesn't allow you to get the height of an element to use in calc() for positioning and margins, so a little JS is needed.
CSS:
.body {
background: #aaf;
height: 300px;
width: 300px;
overflow: hidden;
}
.inner, .body:hover .inner {
-webkit-transition:all linear 0.2s;
transition:all linear 0.2s;
}
.inner {
background: #afa;
width: 300px;
overflow: hidden;
}
.body:hover .inner {
margin-top : 0 !important;
}
JS:
Array.prototype.forEach.call(document.getElementsByClassName('inner'), function (item) {
item.style.marginTop = (item.clientHeight * -1) + 'px';
});
Demo:
http://jsfiddle.net/09tyLr9b/
I added transition to your fiddle to get what i think you are looking for
.inner {
background: #afa;
width: 300px;
overflow: hidden;
max-height: 0;
transition:0.5s ease-out;
}
.body:hover .inner {
max-height: 100%;
transition:0.5s ease-in;
}
JSFIDDLE
and by lowering the time for transition:ease-out you will get a more responsive slide up when you mouse out of the div
like this JSFIDDLE
Another CSS solution after 2.5 years, using flex layout:
.body {
background: #aaf;
height: 300px;
width: 300px;
overflow: hidden;
}
.inner {
display: flex;
align-items: flex-end;
-webkit-transition: all cubic-bezier(0, 1, 0, 1) 0.5s;
transition: all cubic-bezier(0, 1, 0, 1) 0.5s;
background: #afa;
max-height: 0;
overflow: hidden;
}
.body:hover .inner {
-webkit-transition: all ease-in-out 0.5s;
transition: all ease-in-out 0.5s;
max-height: 100%;
}
<div class="body">
<div class="inner">Green is variable-height text which slides in on viewport hover</div>
Blue is a viewport (<body>, visible part of a page), which content should be compressed
Also on JSFiddle.
I want to display images as circle on my webpage. For that, I have an image set as background wrapped inside a div container. Both the divs (outer and inner) have been given a border radius of 50% to achieve this. I also want the image to zoom in oh hover, for which I have applied transform:scale on the inner div.
The image is getting clipped a bit from left and right sides so it doesn't appear as a perfect circle. However, when the image gets scaled up on hover, the image forms a perfect circle. I have tried re-positioning it with background position, tried using a bigger image, increased/decreased size of both divs, but no method is working.
Further, when the image gets zoomed in on hover (using transform:scale), it gets re-positioned slightly after the transformation is complete. Strangely, if I remove the transition effect (transition duration and transition-timing-function), then this re-positioning doesn't happen.
Can anybody figure out why this is happening and what is the solution?
I am using bootstrap (I know it has a class img-circle which draws circle, but I wish to use my own code).
You can see the code running here: http://jsfiddle.net/dk49/h9KZr/
Observe the clipping of image on left and right sides of the circle and how it gets into correct shape on hovering over it. You can also see the jittering of image on zooming when hovering over it.
<div class="container-fluid page-content-wrapper">
<div class="col-xs-12 col-sm-4">
<div class="circle-container">
<h2 class="img-header">Men</h2>
<div class="inner-circle img-men"></div>
</div>
</div>
</div>
CSS:
.page-content-wrapper {
max-width: 980px;
margin-left: auto;
margin-right: auto;
background-color: #000;
}
.circle-container {
max-width: 325px;
max-height:325px;
border-radius: 50%;
overflow: hidden;
position: relative;
margin: 20px auto 0 auto;
z-index: 5; /* for fixing chrome bug */
}
.inner-circle {
width: 100%;
height: 100%;
padding-bottom: 100%;
border-radius: 50%;
overflow: hidden;
position: relative;
transition: transform 0.15s ease-in-out;
}
.inner-circle:hover, .inner-circle:active {
transform: scale(1.1);
}
.circle-container:hover .img-header, .circle-container:active .img-header{
bottom: 30%;
background-color: rgba(255,255,255,0.9);
}
.img-header {
color: #fff;
bottom: 10%;
position: absolute;
width: 100%;
color: #000;
background-color: rgba(255,255,255,0.7);
font-size: 25px;
font-weight: 500;
padding: 7px;
text-align: center;
height: 43px;
vertical-align: middle;
z-index: 1;
transition: bottom 0.15s ease-in-out, background-color 0.15s ease-in-out;
}
.img-header:hover ~ .inner-circle, .img-header:active ~ .inner-circle {
transform: scale(1.1);
}
.img-men {
background: url(http://s8.postimg.org/qohfig4md/men.png) center center no-repeat;
background-size: contain;
}
Goal
I would like to create an animated polygon which has parts of it trimmed/cut/masked out so the layer/element/background under it can be seen like this:
I created an animation with CSS3 transform. It is a rotating block that looks like its bottom parts are trimmed down while moving. I would like the trimmed part to show what is actually behind/under the rotating block (so its background).
What I tried
Illusion solution
For single color backgrounds, you can just add a shape on top of the animation so it have the illusion of being cut off.
This obviously doesn't work with pictures:
Limited solution
If you need to cut off the sides in with a rectangular shape, you can do that by a parent element, but this has obvious limitations. How to do something like this but with an arbitrary polygon? Can you mask in CSS?
body {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAG0lEQVQYV2NMqL7ty4ADMIIkF7SqbsYmP+gkAbAbGgsk/ddhAAAAAElFTkSuQmCC);
}
.center {
width: 200px;
margin: 0 auto;
padding-top: 50px;
height: 100px;
overflow: hidden;
}
.block {
height: 100px;
width: 100px;
background-color: red;
z-index: -1;
transition: transform 1000s 0s linear;
margin-left: 50px;
}
#keyframes rotating {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.rotate {
animation: rotating 2s linear infinite;
}
<div class="center">
<div class="block rotate"></div>
</div>
to trigger z-index, you need to reset position to either: relative, fixed or absolute.
DEMO
#mask {
height: 100px;
width: 100px;
background-color: white;
z-index: 1;
position:relative;/* to trigger z-index */
}
To look like last example, background-position can be efficient.
DEMO box cut off from background
basicly:
body {
background: url('http://takeinsocialmedia.com/wp-content/uploads/2014/02/cute-kitten-images-photos-0223204033.jpg') fixed;
background-size:100vw auto;
background-repeat: no-repeat;
}
#mask {
height: 100px;
width: 100px;
background:url('http://takeinsocialmedia.com/wp-content/uploads/2014/02/cute-kitten-images-photos-0223204033.jpg') fixed;
background-size:100vw auto;
z-index: 1;
position:relative;
}
Unfortunately, this won't work with background-size:cover; since body and #mask have different size. background-size will need to be set via javaScript onload and onresize for #mask.
Have you tried to make the white box invisible with bigger z-index than the red box ?
Here you go: http://jsfiddle.net/QxG74/2/
Cute kitting version: http://jsfiddle.net/DpfW7/1/
Give the center div a height of 100 pixels and set the overflow to hidden. This way the rotating square get's trimmed at the bottom.
#center {
width: 200px;
height: 100px;
overflow: hidden;
}