CSS3D translationZ and translationY thinking error - html

I am making a great thinking mistake here I think.
Please check out this fiddle: http://jsfiddle.net/kimgysen/zdP8q/
I want to understand how to build a spinning cube myself in 3D instead of just copying it, so I'm experimenting; but at the first stage I already get stuck.
First the code:
<section class="container">
<div id="cube">
<figure class="front">1</figure>
<figure class="back">2</figure>
<!--
<figure class="right">3</figure>
<figure class="left">4</figure>
<figure class="top">5</figure>
<figure class="bottom">6</figure>-->
</div>
.container {
width: 200px;
height: 200px;
position: relative;
margin: 0 auto 40px;
border: 1px solid #CCC;
-webkit-perspective: 1000px;
perspective: 1000px;
}
#cube {
margin: 0px;
width: 100%;
height: 100%;
position: absolute;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transition: -webkit-transform 1s;
transition: transform 1s;
-webkit-transform: rotateX( -20deg ) rotateY( 20deg );
transform: rotateX( -20deg ) rotateY( 20deg );
}
#cube figure {
margin: 0px;
display: block;
position: absolute;
width: 196px;
height: 196px;
border: 2px solid black;
line-height: 196px;
font-size: 120px;
font-weight: bold;
color: white;
text-align: center;
}
#cube.panels-backface-invisible figure {
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
}
#cube .front { background: hsla( 0, 100%, 50%, 0.7 ); }
#cube .back { background: hsla( 60, 100%, 50%, 0.7 ); }
#cube .front {
-webkit-transform: translateZ( 100px );
transform: translateZ( 100px );
}
#cube .back {
-webkit-transform: rotateX( 90deg ) translateZ( 100px );
transform: rotateX( 90deg ) translateZ( 100px );
}
What I wonder about is this line:
-webkit-transform: rotateX( 90deg ) translateZ( 100px );
Now this is going to be a very stupid question for you, but still:
Why is it that translateZ moves the figure upwards across the Y-axis?
When changing translateZ into translateY, it is moved across the Z-axis :-s
-webkit-transform: rotateX( 90deg ) translateY( 100px );
Since primary school I thought that: X-axis = horizontal, Y-axis = vertical and Z-axis is the axis that is pendicular on both (ie. pointing towards you).
Can someone please explain to me what's happening? I feel very stupid at this point =s

Yes, the axis work as you say.
But, when you do a rotation, you are not rotaing the object; you are rotating the object space.
So, after a X axis rotation, the z axis can become the y axis. (at 90 deg), can become the z axis inverted (at 180 deg), can become the y axis inverted (at 270 deg), and can revert to z axis at 360 deg.
And, of course, in between it is not aligned with any axis and the movement goes thru a diagonal axis.

Looks like you need a logical starting point to get this sorted out in your head.
Set all your cube sides/panels to position:absolute; and transform-origin: center;
Now we know all our panels will move relative to the same spot, the center of the panel.
So, we make this 3D now by pushing these panels away from it's default Z orientation.
In order to make a cube, we need to translate these panels away from their default Z orientation of 0 (which we need to preserve in order to have a nice anchor to spin on when we animate) by HALF of the width of the panels because... well, geometry.
Now all we need to do is spin these things around the axis with rotateY and rotateX (90deg, 180deg, -90deg) etc.
Then just take the whole thing and animate a spin on it.

Related

Apply different animations to multiple backgrounds images in a single class

I have a single class named slider .I need to have different types of animation for different images.Please help me to implement that .Now all my images are having same mode of animation.I just want to keep a single class slider.
Here is my code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
body{
margin:0p;
padding:0p;
background: green;
perspective: 800px;
height: 100vh;
width: 100wh;
}
.slider{
/* background-image: url(https://www.mozilla.org/media/img/logos/firefox/logo-quantum.9c5e96634f92.png);
background-size: 800px 800px;
width: 800px;
height: 800px;
border: 2px solid;
color: pink;
*/
width:100vw;
height:100vh;
background: url(b1.jpg);
background-size: 100wh 100vh;
/* animation: slide 2s infinite;*/
animation: slide
2s infinite;
margin: 100px auto;
}
#keyframes slide{
from{
/* transform:rotateY(0deg);*/
/* transform: rotate3d(1, 1, 1, 0deg);*/
transform: rotate3d(0, 1, 0, 0deg);
background-color: pink;
}
to{
/* transform:rotateY(180deg);
transform: rotate3d(1, 1, 1, 360deg);*/
transform: rotate3d(0, 1, 0, 360deg);
background-color: pink;
}
25%{
background-image: url(b2.jpg);
background-size: 100wh 100vh;
}
50%{
background-image: url(b3.jpg);
background-size: 100wh 100vh;
}
75%{
background-image: url(b4.jpg);
background-size: 100wh 100vh;
}
100%{
background-image: url(b5.jpg);
background-size: 100wh 100vh;
}
}
</style>
</head>
<body>
<div class="slider"></div>
</body>
</html>
Here is the fiddle
My fiddle
Also one more doubt in each image there seems to be a repetition of image as if the same image gets reduced and a part of the image is getting added there .I just want to have a single image with 100% view not repetition.
Any help would be highly appreciated
This is called a slider and looking at the keyframes definition it seems as though you want to rotate a set of images in order using one animation, not different animations for each image. Tfhis is doable as long as you don't want totally different animations for each 'slide'.
A couple of points:
Your 'doubt' is justified. The image is being repeated as that is the default for background in CSS, set it to 'no-repeat' so you don't get the little extra bits.
The images may (or may not, depends on your use case, but in general) have differing aspect ratios and they may be different or not from the aspect ratio of the viewport (which the containing element uses to set its dimensions). Use either background-size: contain to ensure you see the whole image for every one, or cover if you want to have the entire viewport covered, though in that case either the top and bottom or the side may get cropped to fit
You probably want the background-position to be centered both horizontally and vertically rather than left and top which would be the default in this case.
Here's an altered snippet. Note that the sizes transform over a short time which you may or may not want. You can alter the keyframes to stop that (let me know if you need help with that). Also the very last image has no time to show itself so you probably want to look at the % settings to make sure it gets a look in.
body {
margin: 0p;
padding: 0p;
background: green;
perspective: 800px;
height: 100vh;
width: 100wh;
}
.slider {
/* background-image: url(https://www.mozilla.org/media/img/logos/firefox/logo-quantum.9c5e96634f92.png);
background-size: 800px 800px;
width: 800px;
height: 800px;
border: 2px solid;
color: pink;
*/
width: 100vw;
height: 100vh;
background: url(https://picsum.photos/id/1023/300/300);
background-repeat: no-repeat no-repeat;
/* ADDED */
background-position: center center;
/* ADDED */
background-size: cover;
/* ADDED - TRY BOTH TO DECIDE WHICH YOU WANT IF YOU HAVE IMAGES OF DIFFERENT ASPECT RATIOS */
background-size: contain;
/* ADDED */
background-size: 100wh 100vh;
/* animation: slide 2s infinite;*/
animation: slide 2s infinite;
margin: 100px auto;
}
#keyframes slide {
from {
/* transform:rotateY(0deg);*/
/* transform: rotate3d(1, 1, 1, 0deg);*/
transform: rotate3d(0, 1, 0, 0deg);
background-color: pink;
}
to {
/* transform:rotateY(180deg);
transform: rotate3d(1, 1, 1, 360deg);*/
transform: rotate3d(0, 1, 0, 360deg);
background-color: pink;
}
25% {
background-image: url(https://picsum.photos/id/1015/1024/768);
background-size: 100wh 100vh;
}
50% {
background-image: url(https://picsum.photos/id/1016/768/1024);
background-size: 100wh 100vh;
}
75% {
background-image: url(https://picsum.photos/id/1018/200/300);
background-size: 100wh 100vh;
}
100% {
background-image: url(https://picsum.photos/id/1020/300/300);
background-size: 100wh 100vh;
}
}
<div class="slider"></div>
UPDATE
In the above snippet each image gets the same animation. The requirement is for each to have its own (rotation, zoom et al). This can be achieved while still maintaining the single slider class requirement by having each part of the keyframes define the animation for that particular slide.
In this snippet there are 4 slides, each takes one quarter of the overall alloted time for one iteration of the animation. In each part the particular animation required is defined. This snippet assumes that you want to do the animation bit for half the time an image has the show it without moving for the remaining half. These timings can be altered by altering the %s in the keyframes.
The first image rotates, the second image zooms, the third image comes in from 0 opacity and the fourth image just shows without moving.
Obviously more images can be added and different types of movement, scaling, opacity defined by altering %s and inserting more background images.
Note: opacity will refer to the whole element, so the backgroud pink color also faded which looked odd so I removed it. If it is important to have a background you will have to think about an extra element and animating that, or decide not to use opacity as one of the things that change, or have green to pink change anyway.
body {
margin: 0p;
padding: 0p;
background: green;
perspective: 800px;
height: 100vh;
width: 100wh;
}
.slider {
width: 100vw;
height: 100vh;
background-repeat: no-repeat no-repeat;
/* ADDED */
background-position: center center;
/* ADDED */
background-size: cover;
/* ADDED - TRY BOTH TO DECIDE WHICH YOU WANT IF YOU HAVE IMAGES OF DIFFERENT ASPECT RATIOS */
background-size: contain;
/* ADDED */
animation: slide 16s infinite;
margin: 100px auto;
}
#keyframes slide {
0% {
transform: rotate3d(0, 1, 0, 0deg);
opacity: 1;
background-image: url(https://picsum.photos/id/1023/300/300);
}
12.5%,
24.99% {
/* to make the slide not move between those times */
transform: rotate3d(0, 1, 0, 360deg);
opacity: 1;
background-image: url(https://picsum.photos/id/1023/300/300);
}
25% {
transform: rotate3d(0, 0, 0, 0deg) scale(1);
opacity: 1;
background-image: url(https://picsum.photos/id/1015/1024/768);
}
37.5%,
49.99% {
/* so it scales up for the first half of its time, then stays there showing */
transform: rotate3d(0, 0, 0, 0deg) scale(1.5);
opacity: 1;
background-image: url(https://picsum.photos/id/1015/1024/768);
}
50% {
transform: rotate3d(0, 0, 0, 0deg) scale(1);
opacity: 0;
background-image: url(https://picsum.photos/id/1016/768/1024);
}
74.99% {
transform: rotate3d(0, 0, 0, 0deg) scale(1);
opacity: 1;
background-image: url(https://picsum.photos/id/1016/768/1024);
}
75% {
transform: rotate3d(0, 0, 0, 0deg) scale(1);
opacity: 1;
background-image: url(https://picsum.photos/id/1018/200/300);
}
100% {
transform: rotate3d(0, 0, 0, 0deg) scale(1);
opacity: 1;
background-image: url(https://picsum.photos/id/1018/200/300);
}
}
<div class="slider"></div>
The overall aimation has time of 16s to give each image 2 seconds to move and 2 seconds staying still.
You will find that you need to play around with opacity to stop very sudden changes if this is a problem.
The snippet repeats both the transform and the opacity setting each time which is not always necessary, but I find it serves as a reminder that transform needs all the settings in it, it's not 'cumulative'.

CSS Transforms giving divs an outline

Im building an isometric grid of cubes created with css but im running into an issue with outlines.
Heres what I would like to achieve:
cube design
But heres what i've got so far:
html cube
I've tried the usual tricks like using some translateZ and backface visibility but to no avail.
My css is looking like this:
.cube {
transform: rotateX(55deg) rotateZ(45deg) translateX(50%) translateY(-50%);
transform-origin: 0% 0%;
transform-style: preserve-3d;
position: relative;
pointer-events:all;
transition: background-position ease 7s;
background-size: 400% 400%;
div {
position: absolute;
transition: background-position ease 7s;
backface-visibility: hidden;
&:first-child {
transform-origin: center top;
width: 100%;
height:100%;
transform: rotateX(-90deg);
top: 100%;
}
&:nth-child(2) {
transform-origin: left center;
width: 100%;
height: 100%;
left: 100%;
transform: rotateY(90deg);
}
}
Any ideas would be hugely appreciated.
codepen link
The trick here would be to have the faces of the cubes to overlap and use the background-blend-mode CSS attribute to have them blend into each other. That causes the cubes to blend into each other and get rid of the weird borders.
Working codepen link here: https://codepen.io/anon/pen/LXzWjJ
You might need to play around with the transforms and dimensions a bit to get the exact result you want.
It's not the best solution but it seems to work.
Hope this helps!

Horizontal CSS only parallax effect with layers greater than 100vw

How to bootstrap a site with horizontal CSS only parallax effect?
Requirements
CSS only parallax
parent layer must have width/height == 100vw/100vh
child layers must have width/height > 100vw/100vh
child layers must visually align 100% with parent layers width
by now the child layers technically do have 100% of parents width but due to the perspective they visually don't appear to take 100% of parents width
child layers (except the first) must have a top offset relative to its parent
results must base on calculations to have maximum flexibility
must be cross browser solid (at least newest version of majors)
What I have done so far
Actually this question is a follow-up question.
Here's a PEN with my current mockup state in SASS or CSS.
Working Simulated Example (jQuery)
In JavaScript its quite simple to achieve what I'm looking for. So here is a PEN that simulates the effect I'd like to mimic with CSS.
Already known Issues
The issue I'm most concerned about by now is the fact, that browser seem to render this scenario differently. See screenshot of browser window (chrome vs ff) scrolled to the right bottom corner below. But I hope this could be avoided.
There are so many parallax tutorials out there. Why is this different?
Actually I researched really a lot but didn't find not even one description how to implement horizontal parallax (means the child layers have a width > 100vw). Of course there are horizontal parallax scroll tuts out there. But they all have one in common: the child layer widths are always <= 100vw - and thats actually the difference.
html,
body {
height: 100%;
overflow: hidden;
width: 100%;
}
body {
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
#projection {
-webkit-perspective: 1px;
perspective: 1px;
-webkit-perspective-origin: 0 0;
perspective-origin: 0 0;
height: 100%;
overflow: auto;
width: 100%;
}
.pro {
-webkit-transform: scale(1) translate(0px, 0px) translateZ(0px);
transform: scale(1) translate(0px, 0px) translateZ(0px);
height: 100%;
position: absolute;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
width: 100%;
}
.pro--1 {
-webkit-transform: scale(4) translate(0px, 0px) translateZ(-3px);
transform: scale(4) translate(0px, 0px) translateZ(-3px);
width: 110%;
}
.pro--2 {
-webkit-transform: scale(3) translate(0px, 1em) translateZ(-2px);
transform: scale(3) translate(0px, 1em) translateZ(-2px);
width: 110%;
}
.pro--3 {
-webkit-transform: scale(2) translate(0px, 2em) translateZ(-1px);
transform: scale(2) translate(0px, 2em) translateZ(-1px);
width: 110%;
}
.pro {
background: rgba(0, 0, 0, 0.33);
box-shadow: inset 0 0 0 5px orange;
color: orange;
font-size: 4em;
line-height: 1em;
text-align: center;
}
.pro--2 {
box-shadow: inset 0 0 0 5px green;
color: green;
}
.pro--3 {
box-shadow: inset 0 0 0 5px blue;
color: blue;
}
<div id="projection">
<div class="pro pro--1">pro--1</div>
<div class="pro pro--2">pro--2</div>
<div class="pro pro--3">pro--3</div>
</div>
I'm not 100% certain I've gotten exactly what you're targeting, but I've at least got a step forward for you. In this article on pure-css parallax sites, there was an update regarding working around webkit related bugs by using perspective-origin-x: 100% and transform-origin-x: 100%.
If I apply this in both x and y directions to your current mockup case with sass, I end up changing just #projection and .pro to be like this:
#projection
perspective: $perspective + 0px
perspective-origin: 100% 100%
height: 100%
overflow: auto
width: 100%
.pro
#include projection()
height: 100%
position: absolute
transform-origin: 100% 100%
transform-style: preserve-3d
width: 100%
And the parallax behavior starts to look much more like I might expect. Here is the final pen: https://codepen.io/kball/pen/qPbPWa/?editors=0100

Expandable div that's rotated with css

I am trying to create a page layout with a rectangular div on the left side that's rotated 10 degrees, expands with the size of the browser, and doesn't show its edge on the top, left, and bottom. Meaning, the page should appear to be split in the middle on a slant.
My code so far creates the div properly, but when I expand the page you begin to see the edges.
http://jsfiddle.net/jpQvL/1/
HTML
<div id="wrapper">
<div id="right"></div>
</div>
CSS
html, body {
margin: 0;
padding: 0;
height: 100%;
}
#wrapper {
position:relative;
height: 100%;
}
#right {
background: #000;
transition: all 0.5s ease-in-out 0s;
width: 50%;
position: fixed;
min-height: 110%;
transform: rotate(10deg);
top: -73px;
}
The problem is that the tranform property needs render prefixes. You have to add these lines:
-webkit-transform: rotate(10deg);
-moz-transform: rotate(10deg);
-o-transform: rotate(10deg);
-ms-transform: rotate(10deg);
transform: rotate(10deg);
take a look at this
or use one of many prefix-free scripts like this one

How do you align 270deg rotated text to top left?

This should be a very simple problem you would think. I have a box with some title text that I want to rotate -90 degrees. I would like it to be absolutely positioned so that the end of the word is nudged into the top left corner. I can get this to align to the bottom easily enough, but the problem is that with variable length text it seems impossible to have it consistently stay within the container when aligning to the top because things like {top: 0} operate on the title before the transform. For my purposes this only needs work in Firefox. I can use javascript if that is the only solution, but you would think this could be done with just CSS.
You should use transform-origin to adjust the transformation point, along with some creative use of positioning properties.
http://jsfiddle.net/thirtydot/JxEfs/1/
CSS:
#box {
padding: 30px;
position: relative;
border: 1px solid blue;
}
#box > div {
border: 1px solid red;
position: absolute;
top: 0;
right: 100%;
white-space: nowrap;
-webkit-transform: rotate(270deg);
-webkit-transform-origin: right top;
-moz-transform: rotate(270deg);
-moz-transform-origin: right top;
-ms-transform: rotate(270deg);
-ms-transform-origin: right top;
-o-transform: rotate(270deg);
-o-transform-origin: right top;
transform: rotate(270deg);
transform-origin: right top;
}
HTML:
<div id="box">
hello
<div>rotated!</div>
</div>
Can also work without right:100%
Just rotate 270 deg around left top and then translate it back at new 100% width.
transform: rotate(-90deg) translate(-100%, 0);
transform-origin: 0 0;
http://jsfiddle.net/zW7SP/