So i want to know how to calculate translate css property value for element that is scaled from center (css: transform-origin: 50% 50% 0).
Here is my HTML and CSS (FIDDLE: http://jsfiddle.net/rPNyM/)
HTML:
<div id="holder">
<div id="dot"></div>
<div id="box"></div>
</div>
CSS:
#holder {
position: absolute;
width: 500px;
height: 500px;
background: #226699;
}
#dot {
position: absolute;
left: 100px;
top: 100px;
width: 5px;
height: 5px;
background: #ff0000;
z-index: 20;
}
#box {
position: absolute;
left: 100px;
top: 100px;
width: 100px;
height: 100px;
background: #000;
transform: translate(-25px, -25px) scale(0.2,0.2);
transform-origin: 50% 50% 0;
-moz-transform: translate(-25px, -25px) scale(0.2,0.2);
-moz-transform-origin: 50% 50% 0;
}
The black box should be in same (left top) position as red box even when scale value is changed.
Found the answer by my self (tested some calculations).
Just calculate like this (Javascript):
var pad_x = ((elem_width * scale) - elem_width) / 2;
var pad_y = ((elem_height * scale) - elem_height) / 2;
Related
I have an element which has to be scaled from 100px from the left while already having a scale of 0.5. When transforming the origin it is on 50px on the left side and scaling from the wrong side of the line.
When scaling the element I want it to scale from the purple line. Without using the left CSS property.
I tried to use this formula but it was slightly off:
x + (x * scale)
* {
margin: 0;
padding: 0;
}
.box {
position: relative;
width: 100px;
height: 100px;
margin-top: -10px;
}
.example-initial {
background: blue;
transform: scale(0.2);
transform-origin: 100px 0px;
}
.example-wrong {
background: green;
transform: scale(0.5);
transform-origin: 100px 0px;
}
.example-right {
background: red;
transform: scale(0.5);
transform-origin: 200px 0px;
}
.transform-origin-line-example {
position: absolute;
left: 100px;
width: 1px;
height: 200px;
background: purple;
top: 0;
}
<div class="example-initial box"></div>
<div class="example-wrong box"></div>
<div class="example-right box"></div>
<div class="transform-origin-line-example"></div>
The formula you're looking for is:
(x * (1 / (1 - 0.1));
x is the left position.
1 is the full scale.
0.1 is the used scale.
* {
margin: 0;
padding: 0;
}
.box {
position: relative;
background: red;
width: 100px;
height: 100px;
transform: scale(0.1);
transform-origin: calc(100px * (1 / 0.9)) 0px;
}
.example-box {
position: relative;
background: blue;
width: 100px;
height: 100px;
transform: scale(0.5);
transform-origin: calc(100px * (1 / 0.5)) 0px;
}
.transform-origin-line-example {
position: absolute;
left: 100px;
width: 1px;
height: 200px;
background: green;
top: 0;
}
<div class="box"></div>
<div class="example-box"></div>
<div class="transform-origin-line-example"></div>
You can just fix the transform-origin code as
transform: scale(-0.5);
I am trying to move an image when my mouse is over it.
Here's an exemple. When moving hover pictures, the text is smoothly following your mouse and this is what I'm looking for.
Do you have any idea ?
The problem with what I tried is that the image keeps moving when I get out of the violet box. (I would prefer to avoid having to create a box and recognize when I am over the image).
$("#containerScaled").on('mousemove', '.box', function (e) {
$("#followC").css("top", e.clientY)
.css("left", e.clientX);
});
<style>
#containerScaled, #followC {
transition: all 0.9s ease-out;
transform-origin: center;
transform: scale(1, 1);
}
.box {
height:50px;
width:50px;
left: 500px;
top: 50px;
background-color: blueviolet;
position: absolute;
}
.mouseFollow {
position: fixed;
width:70px;
height:20px;
font-size:12px;
pointer-events:none;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="containerScaled" class="container">
<div class="box">test</div>
</div>
<div id="followC" class="mouseFollow"><img src=" image "/></div>
I think you should begin with altering your position based on where your mose is positioned inside your rectangel like so:
if (e.clientX > width/2){
addX = 20;
}
if(e.clientX < width/2){
addX = -20;
}
if(e.clientY > height/2){
addY = 20;
}
if(e.clientY < height/2){
addY = -20;
}
This is the first step, that actually makes something "follow" your mouse.
I think you could do some optimization, so that the animation is more crispy, but basically thats the way to go.
I also added
$("#containerScaled").on('mouseleave', '.box', function(e) {
$("#followC").css("top", "50%").css("left", "50%");
});
so that your element will get back to its original position once you leave the :hover area
Because of this I also made you hover area transparent, any lay over the moving element, so that when you hover over the moving element, you wont leave the hover area, and trigger mouseleave
.box{
background-color: transparent;
}
.boxcolored{
position: absolute;
height: 100px;
width: 100px;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
background-color: green;
}
$("#containerScaled").on('mousemove', '.box', function(e) {
var left = parseFloat($(".box").css("left"));
var right = parseFloat($(".box").css("top"));
var width = parseFloat($(".box").css("widht"));
var height = parseFloat($(".box").css("height"));
var addX = 0;
var addY = 0;
if (e.clientX > width/2){
addX = 20;
}
if(e.clientX < width/2){
addX = -20;
}
if(e.clientY > height/2){
addY = 20;
}
if(e.clientY < height/2){
addY = -20;
}
$("#followC").css("top", e.clientY + addY)
.css("left", e.clientX + addX);
});
$("#containerScaled").on('mouseleave', '.box', function(e) {
$("#followC").css("top", "50%").css("left", "50%");
});
#containerScaled {
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 200px;
background-color: red;
}
#followC {
transition: all 0.9s ease-out;
transform-origin: center;
}
.box {
position: absolute;
height: 100px;
width: 100px;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
background-color: transparent;
}
.boxcolored{
position: absolute;
height: 100px;
width: 100px;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
background-color: green;
}
.mouseFollow {
position: relative;
height: 20px;
width: 75px;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="containerScaled" class="container">
<div class="boxcolored"></div>
<div id="followC" class="mouseFollow">HALLO</div>
<div class="box">mouse me</div>
</div>
The box outlined in a red dashed line is the hover area. The yellow box is the visual area which is the approximation of the limits to which the letters can move within.
There is a lag and an offset. The lag is due to transition: 0.9s and the offset is left and top. The lag can be decreased but at the cost of the smooth movement, There are four letters at varying transition times for comparison. Notice that they all stop at the same position (when the mouse is no longer moving within the dashed box), it just that the slower the transition the more movement occurs after the mouse has left the dashed box.
The offset is tougher since there is only two positions that will work: x: right or left and y: top or bottom. If keeping the letters within a box is a concern, then keep the hover area border and background to none and show the offset (visual area) instead.
Note: Do not review this demo in compact mode, view it in full page mode (normal dimensions)
$(".target").on('mousemove', function(e) {
$(".text").css({
"top": e.clientY,
"left": e.clientX
});
});
main {
position:relative;
font: 400 16px/1.2 Arial;
}
.zone {
position: absolute;
z-index: 1;
height: 120px;
width: 110px;
margin: 90px 0 0 90px;
background: gold;
color:white;
text-align:right;
}
.target {
position: absolute;
z-index: 2;
height: 100px;
width: 100px;
margin: 75px;
outline: 3px dashed red;
color:red
}
.text {
position: absolute;
z-index: 3;
top: 90px;
left: 90px;
font-size: 32px;
color:black
}
.A {
transition: all 0.9s ease-out;
}
.B {
transition: all 0.6s ease-out;
}
.C {
transition: all 0.3s ease-out;
}
<main>
<section class="target">Hover Area</section>
<aside class="text A">A</aside>
<aside class="text B">B</aside>
<aside class="text C">C</aside>
<aside class="text D">D</aside>
<section class='zone'><b>Visual Area</b></section>
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Without scale code works fine, but I need to center vertically an already scaled element. I am looking for solution using CSS or JS approaches.
Also I can not use transform-origin CSS property because it's unsupported in some browsers that I need to support...
https://jsfiddle.net/o62ja9r6/17/
.container {
position: fixed;
border: 2px dashed blue;
width: 400px;
height: 300px;
}
.slide {
position: absolute;
width: 76px;
height: 169px;
background-color: red;
}
.vertical-center {
top: 50%;
transform: scale(0.4) translateY(-50%);
/* transform: translateY(-50%); // <--- it works */
}
<div class="container">
<div class="slide vertical-center">
</div>
</div>
Order matters, swap translateY with scale.
.container {
position: fixed;
border: 2px dashed blue;
width: 400px;
height: 300px;
}
.slide {
position: absolute;
width: 76px;
height: 169px;
background-color: red;
}
.vertical-center {
position: relative;
top: 50%;
transform: translateY(-50%) scale(0.4);
}
<div class="container">
<div class="slide vertical-center">
</div>
</div>
Quick Explination
If you have an element that is 100px tall and you translate it along the y-axis by -50% it will move up 50% of it's height, which would be 50px. If you scale that 100px tall element first, down to 40% of it's height, then it will be 40px tall when you try to translate it along the y-axis, which will only move it up 20px.
Instead of translate you can use simple CSS for this
.vertical-center {
top: 0;
left:0px;
bottom:0px;
right:0px;
margin: auto;
transform: scale(0.4);
}
for working demo click here
I am trying to create a "slide" div that is centered in the middle of the screen with a constant aspect ratio.
Combining this trick for centering and this one for the ratio, I came up with this:
HTML
<div class="slide">
<div class="slide-content">
Percentage sized and still centered.
</div>
</div>
CSS
/* slide centered in the middle of the screen + width = 80% */
.slide {
position: fixed;
width: 80%;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: red;
box-shadow: 0 0 30px rgba(0, 0, 0, 0.2);
}
/* aspect ratio of 2:1 */
.slide:before{
content: "";
display: block;
padding-top: 50%;
}
/* stretch the content to the slide size */
.slide > .slide-content {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 40px 60px;
transition: all 0.6s ease-in-out;
}
Fiddle is here: https://jsfiddle.net/3jph853w/
It works beautifully, expect on mobile in landscape view: the trick being based on width, the div is not resized properly and part of it "overflows" outside the screen. You can see it when you resize the fiddle output vertically.
How can I fix it ? I would rather keep it css only, with additional html markup is necessary. I am open to JS, but my project is Angular based and does not use jQuery.
This might be a start
Fiddle demo 100% of viewport
Fiddle demo 80% of viewport
html, body{
margin: 0;
}
.slide{
position: absolute;
width: calc(100vh * 2);
height: calc(100vw * 0.5);
max-width: 100vw;
max-height: 100vh;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.slide-content{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: red;
padding: 40px 60px;
box-sizing: border-box;
transition: all 0.6s ease-in-out;
}
<div class="slide">
<div class="slide-content">
Percentage sized and still centered.
</div>
</div>
add text-align:center; to the bottom of .slide > .slide-content {
I'm doing a site with a "hidden" image. I hide the image using a dark overlay, but now I want the cursor to see through the dark overlay.
An almost working example is here: https://jsfiddle.net/swx5x38j/
What I want to know is, how I make the light div look through the dark overlay div. Is this somehow possible, or should I go for different solution? And does some have a hint on such one?
The code follows here as well. First the CSS:
* {
margin: 0;
padding: 0;
}
#image {
background: url(https://placeimg.com/640/480/animals) center no-repeat;
width: 800px;
height: 600px;
}
#overlay {
opacity: 0.9;
background: #000;
width: 100%;
height: 100%;
top: 0;
left: 0;
position: fixed;
}
#light {
opacity: 1;
top: 50%;
left: 50%;
width: 100px;
height: 100px;
border-radius: 50%;
position: absolute;
background: #fff;
}
The jquery is as follow
$(document).mousemove(function(event) {
$('#light').offset({
top: event.pageY - 50,
left: event.pageX - 50
});
});
And last the HTML
<div id="image"></div>
<div id="overlay"></div>
<div id="light"></div>
instead an overlay, you could use a box-shadow:
$(document).mousemove(function(event) {
$('#light').offset({
top: event.pageY - 50,
left: event.pageX - 50
});
});
* {
margin: 0;
padding: 0;
}
#image {
background: url(https://placeimg.com/640/480/animals) center no-repeat;
width: 800px;
height: 600px;
}
#light {
opacity: 1;
top: 50%;
left: 50%;
width: 100px;
height: 100px;
border-radius: 50%;
position: absolute;box-shadow:0 0 0 3000px rgba(0,0,0,0.9);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="image"></div>
<div id="light"></div>
You can create a fake image and calculate the offset of the background image like this:
CSS
* {
margin: 0;
padding: 0;
}
.image {
background: url(https://placeimg.com/640/480/animals) center no-repeat;
}
#image {
width: 800px;
height: 600px;
top:0px;
left:0px;
}
#overlay {
opacity: 0.9;
background: #000;
width: 100%;
height: 100%;
top: 0;
left: 0;
position: fixed;
}
#fakeImage {
position:absolute;
width: 800px;
height: 600px;
}
#light {
opacity: 1;
top: 50%;
left: 50%;
width: 100px;
height: 100px;
border-radius: 50%;
position: relative;
background: #fff;
overflow:hidden;
}
HTML
<div id="image" class="image"></div>
<div id="overlay"></div>
<div id="light" style="display:none;">
<div id="fakeImage" class="image"></div>
</div>
JS
$(document).mousemove(function(event) {
$('#light').offset({
top: event.pageY - 50,
left: event.pageX - 50
});
var _top = (- $('#light').offset().top) + 'px';
var _left = (- $('#light').offset().left) + 'px';
$('#fakeImage').css({'top': _top, 'left': _left });
});
The random image required a unique class with the same image.
JSFiddle example
Add a massive border to the #light and add a negative margin:
https://jsfiddle.net/mpcmvej6/
.
And remove #overlay.
This method seems the most simple to me.
The good part about this method is that there is no need to support box shadow and it does not require a second image element.
Another method is putting a copy of the image inside #light and move it in the opposite direction of #light.