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>
Related
I'm trying to replicate a design using CSS, a simplified example of this is below:
The pink background should be 50% opacity, however the blue offset shadow/border should be 100% opacity.
I can do the general shapes but not in a way to achieve the desired transparency.
Here is an attempt I made:
.container {
position: relative;
margin: 0 auto;
width: 600px;
height: 200px;
}
.content-wrap {
position: relative;
z-index: 1;
filter: drop-shadow(13px 15px 0 rgb(0,255,255));
width: 60%;
height: 100%;
}
.content {
clip-path: polygon(0 0, 100% 0, 70% 100%, 0% 100%);
background: rgba(255,0,255, 0.5);
height: 200px;
}
.background {
z-index: 0;
position: absolute;
top: 20px;
left: 0;
background: black;
width: 500px;
height: 90px;
margin-top: 50px;
}
<div class="container">
<div class="content-wrap">
<!-- Blue -->
<div class="content">
<!-- Pink -->
</div>
</div>
<div class="background">
<!-- Black -->
</div>
</div>
A couple of aspects are not quite right:
The drop-shadow is visible through the pink, it should just be outside of the element.
The blue should extend to the left-hand edge.
The blue is transparent when I have not assigned it to be, it seems to be related to the child element's background being transparent.
Are there any CSS masters who can figure out a way to do this? The HTML can change if needed.
a box-shadow with skew transformation can do the job here. I am using pseudo-element for the sake of the demo but you can replace them with real elements
.box {
margin: 10px 0;
display: flex;
position: relative;
}
.box::before {
content: "";
position: absolute;
inset: 30% 0;
background: black;
}
.box::after {
content: "";
height: 200px;
width: 50%;
transform-origin: top;
transform: skew(-20deg);
background: rgb(255 0 255/80%);
box-shadow: 25px 25px 0 blue;
}
body {
margin: 0
}
<div class="box">
</div>
I have simple CSS code which scale image inside of parent element.
Image when scaling itself is bigger than a parent. Now I need to cut bigger horizontal sides but the top side will be outside of the parent. For a better understanding look at an image.
In this image is a hover statement which I need to get:
IMAGE
I already tried on parent overflow: hidden but the top side will be cut too.
Like I said I need to get a hover statement like is in image preview instead of my in example code. Is there any option on how I can get it?
.home-treneri {
padding: 56px;
}
.home-treneri-container {
max-width: 1200px;
margin: 0 auto;
display: flex;
flex-flow: row wrap;
}
img {
width: 100%;
transition: all 0.3s ease-in-out;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 0;
}
.background {
position: relative;
background-color: rgba(0, 0, 0, 0.5);
width: 300px;
height: 285px;
}
.trener-card {
position: relative;
cursor: pointer;
}
.trener-card:hover img {
width: 110%;
}
<section class="home-treneri">
<div class="home-treneri-container">
<div class="trener-card">
<div class="background">
<img src="https://lh3.googleusercontent.com/proxy/VpiwIPSxe7FnIAm7aWS7GiB76GDhXeTjqbIst6g0dHYaXWZEyaQ6hfbUqVEuLFqZwG7lsygIjEgf1SQ338Z0djShjmotcVgw5sTQg0Ltf638227HVN7ok3UlIiaUYycmTnJ27hAB055TWk0">
</div>
</div>
</div>
</section>
Adding clip-path: inset(-50px 0 0 0); to your trener-card class will give you the desired result.
What it basically does is clipping the image. On the top you allow the image to grow up to 50px (-50px), while on the other 3 sides you are saying that the image will be clipped (0 0 0)
.home-treneri {
padding: 56px;
}
.home-treneri-container {
max-width: 1200px;
margin: 0 auto;
display: flex;
flex-flow: row wrap;
}
img {
width: 100%;
transition: all 0.3s ease-in-out;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 0;
}
.background {
position: relative;
background-color: rgba(0, 0, 0, 0.5);
width: 300px;
height: 285px;
}
.trener-card {
position: relative;
cursor: pointer;
clip-path: inset(-50px 0 0 0);
}
.trener-card:hover img {
width: 110%;
}
<section class="home-treneri">
<div class="home-treneri-container">
<div class="trener-card">
<div class="background">
<img src="https://lh3.googleusercontent.com/proxy/VpiwIPSxe7FnIAm7aWS7GiB76GDhXeTjqbIst6g0dHYaXWZEyaQ6hfbUqVEuLFqZwG7lsygIjEgf1SQ338Z0djShjmotcVgw5sTQg0Ltf638227HVN7ok3UlIiaUYycmTnJ27hAB055TWk0">
</div>
</div>
</div>
</section>
You should try overflow-x: hidden on parent.
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%;
I am trying to create a graoh to show positive and negative value by percentage so if value will be negative it will be red bar if value will be positive it will run red bar so the thing is that I am having issue when I set width to 46 or 50% the bar is showing to be of full size as it shouldn't be can anyone help me out with this please
.box {
position: relative;
width: 400px;
height: 30px;
background-color: #333
}
.bar_red {
background-color: #d40216 !important;
left: 50%;
width: 13%;
max-width: 180px;
}
.bar_green {
right: 50%;
}
.bar_green,
.bar_red {
width: 42%;
height: 20px;
background-color: #88c500;
position: absolute;
top: 50%;
transform: translateY(-50%);
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
}
<div class="box">
<div class="bar_red" style="width: 50%;"></div>
<div class="bar_green" style="width: 50%;"></div>
</div>
https://jsfiddle.net/vck8wchh/
First of all your bars are pulled 50%. see example below
.bar_green {
right: 50%;
}
.bar_red {
left: 50%;
}
So this means that if you fill in 50% or higher in your <div style="50%"> it will be full width. Go to your fiddle and for example replace your HTML with the following:
<div class="box">
<div class="bar_red" style="width: 10%;"></div>
<div class="bar_green" style="width: 30%;"></div>
</div>
You'll see that they won't be fully filled. new jsfiddle
May I suggest a simpler solution? In my snippet the green bar is 100% wide, while the red bar gets a percentage width, is right-aligned and covers the green one using a higher z-index. So you only have to set the percentage of the red bar.
.box {
position: relative;
width: 390px;
height: 20px;
background-color: #333;
border: 5px solid #333;
}
.bar_green,
.bar_red {
height: 20px;
position: absolute;
}
.bar_green {
left: 0;
width: 100%;
background-color: #88c500;
z-index: 1;
}
.bar_red {
background-color: #d40216 !important;
right: 0;
width: 42%;
z-index: 2;
}
<div class="box">
<div class="bar_red"></div>
<div class="bar_green"></div>
</div>
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