CSS make cube with skew and rotate - html

I am trying to make cube with 3 square divs and CSS.
The problem appears with the top side: I can't find a way to give it a proper shape.
Of course, it should be an easy way to do it with matrix or other stuff, but if there's a way to solve this problem using only skew and rotate, please provide it.
Thanks in advance.
html:
<div id='box' class='top'></div>
<div id='box' class='left'></div>
<div id='box' class='right'></div>
CSS:
#box {
width: 50px;
height: 50px;
}
.top {
background: #bbf;
margin: 40px 0 0 24px;
transform: rotate(-30deg) skewX(30deg); /* ??! */
}
.left {
background: #fbb;
transform: rotate(30deg) skewX(30deg);
display: inline-block;
margin: -11px 0 0 0;
}
.right {
background: #bfb;
transform: rotate(60deg) skewY(30deg);
display: inline-block;
margin: -11px 0 0 -11px;
}
EDIT: thanks to #rby, I reordered the layers a bit
See at jsfiddle

Here's one way to do it using only skew and rotate as you specified, but with a few additional modifications. First, and most important, arrange the order of your divs so that the div for the top box is first, followed by the two sides. The way you have it now, the top div (class third) is last. Then, the other modifications I did was to use a block display for the top div and add a left margin to it so that it is pushed in towards the side divs and reduce the top margin on the side divs from 50px to 10px. With these changes and your existing rotate, skewX transforms, you get a cube.
Here's the modified code - not to disrupt your code too much I simply created a new id called boxTop for the top box but it'd be best to restructure the rules.
The divs:
<div id='boxTop' class='third'></div>
<div id='box' class='first'></div>
<div id='box' class='second'></div>
The CSS:
#box {
width: 100px;
height: 100px;
margin-top: 10px;
display: inline-block;
}
#boxTop {
width: 100px;
height: 100px;
display: block;
}
.third {
background: #bbf;
margin-left: 50px;
transform: rotate(-30deg) skewX(30deg); /* ??! */
}
Hope this solves your problem.

Related

What is the best way to avoid font-size scaling when transforming its container?

I am using css transform: scale to animate the entering of a modal. The problem is that the text scale with the <div> that contains it.
How can I avoid?
I want to use scale because it is the suggested way for obtaining smoother animations.
Without your code, it is hard to give you a working answer.
Basically, you cannot exclude a child element from its parent element being scaled. You can accomplish what you want by separating the two elements.
There is more information here.
What you can do is transform both the container and text.
The container is scaled up, while the text is scaled down - so it appears to stay the same.
Here is a very basic example:
button:focus + div {
transform: scale(2);
}
button:focus + div p {
transform: scale(.5);
}
div {
width: 200px;
margin: 0 auto;
text-align: center;
background: black;
color: white;
}
<button>Click to scale box</button>
<div>
<p>Do not scale this text</p>
</div>
#MalloreeEady answer, I just enhanced the answer from the post. Text that are related from the parent container usually get affected by any transformation. To able to avoid that, you may need to create another tag inside or use the pseudo-elements.
h2 {
color: #ffffff;
}
.box {
position: relative;
width: 50%;
height: 50%;
padding: 10px;
text-align: center;
margin: 50px auto;
}
.box::before {
content: '';
position: absolute;
top: 0; left: 0;
display: block;
background: #000;
width: 100%;
height: 100%;
z-index: -1;
}
.box:hover::before {
-webkit-transform: scale(1.3);
-ms-transform: scale(1.3);
transform: scale(1.3);
}
<div class="box">
<h2>TEST TEXT</h2>
</div>

Joining diagonal divs with flex

I have 2 divs. Right div is an image cutted diagonally. Left divs must have some text inside. I want this to be fully responsive like this:
The problem occurs when I change window size, it's collapsing like in the image:
.
Also there is a text on left div that need to be displayed, but with flex this seems not to work so i disabled it. Please provide solution for this.
Here is my css and html:
#diagonal {
display: flex;
width: 100%;
}
#diagonal #ct-about-col-left {
width: 60%;
border-right: 190px solid transparent;
border-bottom: 500px solid grey;
z-index: 2;
}
#diagonal span {
display: none;
}
#ct-about-col-right {
height: 500px;
width: 50%;
border: 2px solid;
background-image: url(images/content/about/right-col-image.jpg);
z-index: 0;
margin-left: -12%;
margin-right: 0;
}
}
<div id="diagonal">
<div id="ct-about-col-left">
<span>We are the best</span>
<span>text1 text1 text1</span>
<span>Text2 text2 text2 text2</span>
<div>
<span>Read more</span>
</div>
</div>
<div id="ct-about-col-right"></div>
</div>
Maybe consider a slightly different mark-up and method of adding the picture (as a background-image) and making the angle (with transform: skew).
Live Demo: http://codepen.io/anon/pen/rjyKRo
<div class="container">
<div class="caption">
<p>CONTENT</p>
</div>
</div>
* { box-sizing: border-box; }
.container {
width: 100%;
height: 50vh;
overflow: hidden;
background-image: url("http://unsplash.it/600");
background-size: cover;
background-repeat: no-repeat;
background-position: 100% 50%;
}
.caption {
height: 100%;
width: 50%;
min-width: 500px;
padding-top: 20%;
padding-left: 130px;
background-color: #ddd;
transform: skew(10deg, 0deg);
transform-origin: 100% 100%;
}
.caption p {
transform: skew(-10deg, 0deg);
}
May I suggest another approach which will save You some markup space and CSS rules as well.
Simply create a full-width div with the ID of lets say ct-about, give it a background color grey and then simply chain the image background on top of the color like so:
background: url('images/content/about/right-col-image.jpg') no-repeat right top, grey;
This simply tells the browser, make my box grey and put that image over the grey color. The no-repeat right top properties are preventing the browser from repeating the image so you don't get a tile, tell ti to place the image on the far right and top positions.
This way everything will be responsive as well.
Here is a Fiddle for You to better understand.
You can find more information about multiple CSS backgrounds in the Mozilla Developer Network

Triangular Images

I have two right triangle images that I want to put together like this (solid colors only for example):
I can think of a couple of ways to do this:
Divs with background images, and positioning them on top of each
other
A similar approach to the above, but with images instead of divs
The problem comes from the fact that I want to be able to hover (and click) on each individual triangle and have it change it's state (such as change color on hover).
Both of my above solutions create the problem where one is on top of the other, and I cannot click or hover over the other. I was thinking of doing this with CSS shapes, but those usually involve borders and I don't know of a way to overlay the image on those.
I need to be able to accomplish this with just CSS and HTML, and ideally without an image map.
Is this what you want?
Edit: I didn't notice there was another answer with similar approach, had the answer window opened for awhile, sorry.
.container {
width: 100px;
height: 100px;
overflow: hidden;
position: relative;
}
.triangle {
position: absolute;
width: 100px;
height: 100px;
top: 0;
left: 0;
overflow: hidden;
}
.triangle:hover {
border: 1px solid red;
}
.top_right {
transform: skewX(45deg);
transform-origin: 0 0;
}
.top_right img{
transform: skewX(-45deg);
transform-origin: 0 0;
}
.bottom_left {
transform: skewX(45deg);
transform-origin: 0 100%;
}
.bottom_left img{
transform: skewX(-45deg);
transform-origin: 0 100%;
}
<div class="container">
<div class="triangle top_right">
<img src="http://www.avatarsdb.com/avatars/spongebob_happy.jpg">
</div>
<div class="triangle bottom_left">
<img src="http://www.avatarsdb.com/avatars/say_cheese.jpg">
</div>
</div>
Another option is to use css skew:
your html:
<div class="img-container">
<img src="http://www.natureasia.com/common/img/splash/thailand.jpg" />
</div>
<div class="img-container">
<img src="http://www.worddive.com/blog/wp-content/uploads/2014/06/nature-and-environment-course.jpg"/>
</div>
The css:
.img-container, .img-container img { width: 100%; height: 100%; }
.img-container {
overflow: hidden;
position: absolute;
transform: skewX(-68deg);
}
.img-container:first-child {
left: -.25em;
transform-origin: 100% 0;
}
.img-container:last-child {
right: -.25em;
transform-origin: 0 100%;
}
.img-container img {
transform: skewX(68deg);
transform-origin: inherit;
}
It will probably work better with square images, however you can play around with the skew until it looks right.
Check out this Fiddle or rotating the other way
Again, not 100% sure on browser compatibility tho. If you need to guarantee that all browsers render properly you might be best of using images.

Rotate div 90 degrees and position fixed in the upper left corner

This is what I'm trying to accomplish:
I want to have a navigation that will be rotated 90 deegres and fixed to the upper left corner of the window.
HTML:
<div class="outer">
<div class="inner">
<ul class="list">
<li class="item">lasange</li>
<li class="item">spaghetti</li>
</ul>
</div>
</div>
CSS:
.outer {
position: fixed;
left: 20px;
top: 20px;
background: red;
}
.inner {
-webkit-transform: rotate(-90deg);
transform-origin: 0 0;
background: green;
}
I can't get it to look like in the image above. The problem is with the rotation. The inner div is positioned and then rotated, and as a result ends up outside the outer div. No matter what I put as the origin of the transformation it doesn't work the way I want it to. I've tried positioning the inner div with position: absolute but with no luck. I don't know the height/width parameters of the menu list.
Here's a fiddle: https://jsfiddle.net/949cjcnq/7/
Any help would be greatly appreciated.
Best regards,
Paul
So I manage to position it the way you want, no matter how big your content is using position: absolute; for your .inner-div.
The only drawback is that your text is facing downwards and not upwards. Couldn't get around that issue with my CSS :S
If you -webkit-transform: rotate(180deg); the child of .inner you can turn the text the right way up :)
.outer {
position: fixed;
left: 20px;
top: 20px;
background: red;
}
.inner {
position: absolute;
bottom: 100%;
-webkit-transform: rotateZ(90deg);
transform-origin: 0 100%;
background: #AACAD7;
white-space: nowrap;;
}
.rotate {
-webkit-transform: rotate(180deg);
}
ul { list-style: none; padding: 0; margin: 0; white-space: nowrap; }
ul li { padding: 5px 10px; }
<div class="outer">
<div class="inner">
<ul class="list rotate">
<li class="item">lasange | spaghetti</li>
</ul>
</div>
</div>
I think what you want to do is move the rotation from the inner to the outer class. Your css should look like this:
.outer {
-webkit-transform: rotate(-90deg);
position: fixed;
left: 20px;
top: 80px;
background: red;
}
.inner {
background: green;
}
To make the text appear side by side after rotation, using a table would work better than using a list:
<div class="outer">
<div class="inner">
<table class="list">
<tr>
<td class="item">lasange</td>
<td class="item"> | </td>
<td class="item">spaghetti</td>
<tr>
</table>
</div>
</div>
Working Fiddle: https://jsfiddle.net/949cjcnq/12/
Despite what you chose for the angle or rotation unfortunately you cannot do this without knowing the width of your item, as such I don't think it can be done in pure CSS/CSS3 without an expanded framework. As such to solve this you will need to use some JavaScript and get the computed width of the element and change the transformation appropriately:
var inner = document.querySelectorAll('.inner')[0];
var width = inner.offsetWidth;
inner.style.transform = "translateY("+width+"px) rotate(-90deg)";
Keep transform-origin: 0 0 as it will have the top of the element to the edge of the screen. Then we simply need to translate in the Y direction by the width, this will place the element in the left corner:
Fiddle Example
In the below snippet you will see that I removed the outer and inner html and just rotated the entire UL -90deg. The result is your example image. Further proper styling is up to you ;-)
See snippet for comments:
/* {outline: 1px dotted red } /* for debugging */
ul, li { list-style-type: none; padding: 0; margin: 0 }
ul { height: 1; /* 1 x line-height */
position: relative;
float: left;
padding: 0 6px;
/* would be regular without transform */
top: 20px; left: 20px;
/* but transform-origin now pivots around
top-right so UL element gets moved right.
So left position needs correction:
left = -1 x (total width of LI's + line-height + UL margin-LR + UL padding-LR) + wanted-left-margin */
top: 20px; left: -134px; /* (optically estimated) */
}
li {
display: inline; /* result is horizontal menu */
}
.list {
transform: rotate(-90deg); /* removed -webkit-*/
transform-origin: top right;
background: #acc9d7;
}
<ul class="list">
<li class="item">lasange | </li>
<li class="item">spaghetti</li>
</ul>
You can add a translateX(-100%) to your transform, that will set it where you want
.outer {
position: fixed;
left: 20px;
top: 20px;
background: red;
}
.inner {
-webkit-transform: rotate(-90deg) translateX(-100%);
transform: rotate(-90deg) translateX(-100%);
transform-origin: 0 0;
background: green;
}
.list {
margin-top: 0px;
}
<div class="outer">
<div class="inner">
<ul class="list">
<li class="item">lasange</li>
<li class="item">spaghetti</li>
</ul>
</div>
</div>

Issue with CSS Enlarge on Hover Effect

I found a nice tutorial for making my images enlarge (like a zoom effect) on hover. The main difference between my needs and a tutorial is that I want my all images contained in a single box like container. So when I implemented the tutorial I realize that part of the enlarged image gets cut off when you hover. The effect is constrained to the container. I would like a way for the zoom to go wherever it needs to go on the page. (So you can see the whole zoomed image)
Here is my implementation of the tutorial: http://mulnix.contestari.com/wp/example225/1.php
JSFiddle: http://jsfiddle.net/dsRAH/
Original Code
Remove the overflow: hidden and all other overflows,
than for your images containers DIV remove float:left; and add display:inline-block;
* {
margin: 0;
box-sizing: border-box;
}
.wrapper {
position: relative;
background: #000;
color: #fff;
z-index: 0;
}
.photos {
position: relative;
display: flex;
flex-flow: row wrap;
}
.photo {
box-shadow: 0 0 0 2px #444;
margin: 5px;
position: relative;
max-height: 200px;
transform: translateZ(0);
transition: transform 0.5s;
}
.photo:hover {
z-index: 1;
transform: translateZ(0) scale(1.6);
}
.photo img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
.photo-legend {
position: absolute;
bottom: 0;
width: 100%;
padding: 1em;
background: rgba(0,0,0,0.3);
}
<div class="wrapper">
<div class="photos">
<div class="photo">
<img src="https://placehold.it/200x150/0bf" />
<div class="photo-legend">TEST DESCRIPTION</div>
</div>
<div class="photo">
<img src="https://placehold.it/200x200/f0b" />
</div>
<div class="photo">
<img src="https://placehold.it/200x150/bf0" />
</div>
</div>
</div>
It's not perfect but it's a start. I changed the overflow:hidden; in the wrapper to visible. I also put your code into jsfiddle so people can tinker with it.
http://jsfiddle.net/m8FXH/
You can try to use z-index. An element with greater z-index is always in front of an element with a lower z-index. If you main container is not overflow:hidden than you can try this out.
here is an example where you can see how it works. Hope that is helpful.
https://developer.mozilla.org/en-US/docs/Web/CSS/z-index
I would suggest giving your divs one of the following classes:
colleft for the ones that are at left column
colright for the ones that are at right column
rowtop for the ones at the top row
rowbottom for the ones at the bottom row
And then assign them the following properties
.colleft {
transform-origin-x: 0%;
}
....
transform-origin-x: 100%;
transform-origin-y: 0%;
transform-origin-y: 100%;
(respectively)
That will make the zoom go in the desired direction.
evan stoddard modified fiddle