CSS 3D transform acting strange, DIV goes blank - css

Fiddle: http://jsfiddle.net/y7d4kkxz/
HTML:
<div class="app">
<div class="content">
<div class="wrapper">
Content here.
<button class="doit">...</button>
</div>
</div>
</div>
CSS:
.app {
background: #003;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
width: auto;
height: auto;
}
.content {
background: #fff;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: auto;
height: auto;
overflow-x: hidden;
overflow-y: auto;
transition: 500ms;
}
.menu-open .content {
transform: translate3d(40%, 0px, 0px) scale3d(0.85, 0.85, 0);
}
.wrapper {
margin: 5%;
}
JS:
$(function () {
$('.doit').on('click', function () {
$('.app').toggleClass('menu-open');
});
});

scale3d(0.85, 0.85, 0) will scale the Z axis of the element to 0, and it will disappear. You could use 1 instead, but it doesn’t look like you need 3D transformations at all up to this point:
.menu-open .content {
transform: translateX(40%) scale(0.85);
}
Updated fiddle

Related

adjust css of gauge element without breaking

I am simply trying to make this gauge smaller. When I try and do that (modify the container class) it warps the whole gauge element. I change the position to relative and the edge of the gauge seems to break. Any ideas on how to scale this without breaking the gauge? I eventually will nest this inside of a column in bootstrap and just trying to get this working on a basic level. Any advice on this css issue would be helpful
const Gauge = Vue.extend({
template: `
<div class="container">
<div class="gauge-bg"></div>
<div class="gauge-middle"></div>
<div class="gauge-overlay" :style="{ transform: rotate }"></div>
<div class="gauge-data">
<span>{{ percentage }}%</span>
</div>
</div>
`,
props: ['percentage'],
computed: {
rotate() {
const v = this.percentage * 180 / 100;
return `rotate(${v}deg)`;
} } });
new Vue({
el: '#app',
components: {
Gauge
}
});
body {
background-color: #4d4d4d;
}
.container {
width: 400px;
height: 200px;
position: absolute;
top: 0;
overflow: hidden;
}
.gauge-bg {
z-index: 1;
width: 400px;
height: 200px;
position: absolute;
background-color: #a3f6ba;
border-radius: 250px 250px 0 0;
}
.gauge-middle {
z-index: 3;
position: absolute;
background-color: #4d4d4d;
width: 250px;
height: calc(250px / 2);
top: 75px;
margin-left: 75px;
margin-right: auto;
border-radius: 250px 250px 0 0;
}
.gauge-overlay {
z-index: 2;
position: absolute;
background-color: #5df086;
width: 400px;
height: 200px;
top: 200px;
border-radius: 0 0 200px 200px;
transform-origin: center top;
}
.gauge-data {
z-index: 4;
color: #5df086;
position: absolute;
width: 400px;
bottom: 0;
text-align: center;
font-size: 24px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<gauge percentage="33"></gauge>
</div>
The quick and dirty solution is to use transform: scale():
.container {
transform: scale(.5) translateY(-100%);
transform-origin: 0 100%;
}
combined with a font-size increase (optional).
Vue.config.devtools = false;
Vue.config.productionTip = false;
const Gauge = Vue.extend({
template: `
<div class="container">
<div class="gauge-bg"></div>
<div class="gauge-middle"></div>
<div class="gauge-overlay" :style="{ transform: rotate }"></div>
<div class="gauge-data">
<span>{{ percentage }}%</span>
</div>
</div>
`,
props: ['percentage'],
computed: {
rotate() {
const v = this.percentage * 180 / 100;
return `rotate(${v}deg)`;
} } });
new Vue({
el: '#app',
components: {
Gauge
}
});
body {
background-color: #4d4d4d;
}
.container {
width: 400px;
height: 200px;
position: absolute;
top: 0;
overflow: hidden;
transform: scale(.5) translateY(-100%);
transform-origin: 0 100%;
}
.gauge-bg {
z-index: 1;
width: 400px;
height: 200px;
position: absolute;
background-color: #a3f6ba;
border-radius: 250px 250px 0 0;
}
.gauge-middle {
z-index: 3;
position: absolute;
background-color: #4d4d4d;
width: 250px;
height: calc(250px / 2);
top: 75px;
margin-left: 75px;
margin-right: auto;
border-radius: 250px 250px 0 0;
}
.gauge-overlay {
z-index: 2;
position: absolute;
background-color: #5df086;
width: 400px;
height: 200px;
top: 200px;
border-radius: 0 0 200px 200px;
transform-origin: center top;
}
.gauge-data {
z-index: 4;
color: #5df086;
position: absolute;
width: 400px;
bottom: 0;
text-align: center;
font-size: 48px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<gauge percentage="33"></gauge>
</div>
The proper solution would be to rewrite its CSS so that it takes a variable ($gaugeWidth !?) and factors in all its hard-coded sizes so it scales correctly (what the original dev should have done in the first place).

Center div in div vertically and horizontally, position absolute

So I want to center "innerDiv1" vertically and horizontally in "outerDiv".
"innerDiv1" has to be position absolute, so "innerDiv2" can over lap it.
I have tried line-height, this doesn't work because "outerDiv" can change size. Line-height doesn't react to percentage the way I want it to.
Here's my snippet:
html, body {
margin: 0;
}
.wrapper {
background: lightblue;
width: 300px;
height: 300px;
}
.outerDiv {
background: red;
height: 50%;
width: 50%;
}
.innerDiv1 {
background: seagreen;
position: absolute;
}
.innerDiv2 {
background: rgba(255,255,255,0.5);
height: 100%;
}
<div class="wrapper">
<div class="outerDiv">
<div class="innerDiv1">Hello World!</div>
<div class="innerDiv2"></div>
</div>
</div>
Thanks for your help.
See for yourself. See the comments in the CSS on what you need to include.
html, body {
margin: 0;
}
.wrapper {
background: lightblue;
width: 300px;
height: 300px;
position: relative; /* 1. Add this. */
}
.outerDiv {
background: red;
height: 50%;
width: 50%;
position: absolute;
top: 25%; /* 2. Add this. */
left: 25%; /* 3. Add this. */
}
.innerDiv1 {
background: seagreen;
position: absolute; /* 4. Add this. */
top: 50%; /* 5. Add this. */
left: 50%; /* 6. Add this. */
transform: translate(-50%, -50%); /* 7. Add this. */
text-align: center; /* 8. Add this if you want the text to be centered. */
}
.innerDiv2 {
background: rgba(255, 255, 255, 0.5);
height: 100%;
top: 50%;
left: 50%;
}
<div class="wrapper">
<div class="outerDiv">
<div class="innerDiv1">Hello World!</div>
<div class="innerDiv2"></div>
</div>
</div>
Add this to your css:
.outerDiv {
position: relative;
}
.innerDiv1 {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
margin: auto;
}

Flatten a Responsive CSS3 Triangle

I've created a responsive CSS3 triangle using the following guide.
GUIDE
The problem I now face is that I want to decrease its height. So it's not a 90-degree triangle but rather, I want to adjust its height to for example 30 pixels whilst maintaining a skewed triangle shape as well as it's responsiveness.
Here is what I have so far:
p {
margin: 0;
}
body {
background: black;
}
.container {
width: 50%;
margin: 0 auto;
}
.item {
background: white;
}
.tr {
overflow: hidden;
width: 100%;
position: relative;
padding-bottom: 100%;
}
.tr:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 120%;
height: 100%;
background: white;
transform-origin: top right;
transform: rotate(45deg);
}
<div class="container">
<div class="item">
<h1>Some Content</h1>
<p>Dummy Content</p>
</div>
<div class="tr"></div>
</div>
I tried experimenting with the perspective transform but with no luck.
You can scale the element to whatever ratio you want. I've compressed the triangle in my code by 2. Just use transform: scale(1, 0.5) rotate(45deg);
Note: The order of transformations will do matter. The result of
transform: rotate(45deg) scale(1, 0.5); is different from transform: scale(1, 0.5) rotate(45deg);
p {
margin: 0;
}
body {
background: black;
}
.container {
width: 50%;
margin: 0 auto;
}
.item {
background: white;
}
.tr {
overflow: hidden;
width: 100%;
position: relative;
padding-bottom: 100%;
}
.tr:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 120%;
height: 100%;
background: white;
transform-origin: top right;
transform: scale(1, 0.5) rotate(45deg)
}
<div class="container">
<div class="item">
<h1>Some Content</h1>
<p>Dummy Content</p>
</div>
<div class="tr"></div>
</div>
Answer by spooky daimon is way more intuitive, go for that one. Just to show the possibilities, you can also skew the pseudo element and adapt rotation as well as translation.
p {
margin: 0;
}
body {
background: black;
}
.container {
width: 50%;
margin: 0 auto;
}
.item {
background: white;
}
.tr {
overflow: hidden;
width: 100%;
position: relative;
padding-bottom: 100%;
}
.tr:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 120%;
height: 100%;
background: white;
transform-origin: top right;
transform: translate(25%) rotate(30deg) skew(-30deg);
}
<div class="container">
<div class="item">
<h1>Some Content</h1>
<p>Dummy Content</p>
</div>
<div class="tr"></div>
</div>

CSS Keyframes: How to move div to certain position

I have a div I want to move to a certain position (say [200,200]) when I add the class remove. I have a lot of divs from different places and I want them to meet at [200,200].
.remove { -webkit-animation: swoopOut 2s 1 ease forwards; }
#-webkit-keyframes swoopOut {
0% {position: relative; left: 0px; top: 00px; opacity: 1}
80% {position: absolute; left: 200px; top: 200px; opacity: 1}
100% {position: absolute; left: 200px; top: 200px; opacity: 0}
}
When I use top/left, it moves relative (200 down, 200 right) though I want absolute (to [200,200]). I've tried position: absolute but that won't work.
Any help?
EDIT: I've tried to make an example in fiddle where I want the two boxes to meet at 150,50. What can I do?
Lot of divs? With CSS, I'm pretty sure it's not possible without a keyframe rule for each element. With JS, however:
window.onload = function() {
TweenLite.to(document.getElementsByClassName("box"), 1, {
top: 50,
left: 150,
onComplete: function() {
TweenLite.to(this.target, 0.2, {
opacity: 0,
onComplete: function() {
TweenLite.set(this.target, {
opacity: 1
});
this.restart();
}.bind(this)
});
}
});
};
body {
margin: 0px;
}
#container {
position: relative;
}
.wrapper {
/*position: relative;*/
width: 100px;
height: 100px;
border: 1px solid black;
}
.meet {
position: absolute;
top: 50px;
left: 150px;
width: 100px;
height: 100px;
border: 1px solid black;
}
.box {
position: absolute;
width: 100px;
height: 100px;
background-color: coral;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/CSSPlugin.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenLite.min.js"></script>
<div id="container">
<div class="wrapper">
<div class="box"></div>
</div>
<div class="wrapper">
<div class="box"></div>
</div>
<div class="meet"></div>
</div>
Here's with CSS only but with multiple keyframe and animation rules.
body {
margin: 0px;
}
#container {
position: relative;
}
.wrapper {
position: relative;
width: 100px;
height: 100px;
border: 1px solid black;
}
.meet {
position: fixed;
top: 50px;
left: 150px;
width: 100px;
height: 100px;
border: 1px solid black;
}
.box {
position: absolute;
width: 100px;
height: 100px;
background-color: coral;
}
.box1 {
-webkit-animation: boxOne 1s infinite;
}
.box2 {
-webkit-animation: boxTwo 1s infinite;
}
#-webkit-keyframes boxOne {
0% {
left: 0px;
top: 0px;
opacity: 1
}
80% {
left: 150px;
top: 50px;
opacity: 1
}
100% {
left: 150px;
top: 50px;
opacity: 0
}
}
#-webkit-keyframes boxTwo {
0% {
left: 0px;
top: 0px;
opacity: 1
}
80% {
left: 150px;
top: -50px;
opacity: 1
}
100% {
left: 150px;
top: -50px;
opacity: 0
}
}
<div id="container">
<div class="wrapper">
<div class="box box1"></div>
</div>
<div class="wrapper">
<div class="box box2"></div>
</div>
<div class="meet">
</div>
</div>

How to move fluid divs the correct distance on/off screen using CSS3 transforms?

I have a fluid container which contains a number of absolutely positioned fluid divs. I want to use CSS3 transforms to move these on and off the page. The problem i am having is that when using transforms you either use exact pixel amounts or percentages of the element itself.
So you can see an example of the sort of thing i'm referring to (this is just a test example) at http://jsfiddle.net/K3uPY/
This is using a transform of 1000% to move them offscreen which is obviously not a good thing to do as if the display is massive it won't work and it means each div ends up a different distance from off the screen edge so the animations can end up taking quite a different amount of time to complete depending on their original size.
What i want to do it move them all just offscreen based on the viewport width/height (and the related direction).
This can easily be done by animating the top/left positions but this is obviously not optimal on all devices (see http://paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/)
Is there anyway to do this using CSS3 transforms or even keyframes or am i stuck having to animate the left/top positions?
The CSS from the JSfiddle is:
html, body {height:100%; width: 100%; padding:0; margin:0;}
#wrapper {width: 100%; height: 100%; overflow: hidden;}
#container {width:50%; height: 50%; margin: auto; position: relative;}
#container div {
background-color: red;
position: absolute;
height: 25%;
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box; /* Firefox, other Gecko */
box-sizing: border-box; /* Opera/IE 8+ */
border: 2px solid #000000;
-webkit-transition-duration: 600ms;
-moz-transition-duration: 600ms;
-o-transition-duration: 600ms;
transition-duration: 600ms;
cursor: pointer;
}
.zoomleft {
-webkit-transform:translate(-1000%);
-moz-transform:translate(-1000%);
-ms-transform:translate(-1000%);
-o-transform:translate(-1000%);
transform:translate(-1000%);
}
.zoomright {
-webkit-transform:translate(1000%);
-moz-transform:translate(1000%);
-ms-transform:translate(1000%);
-o-transform:translate(1000%);
transform:translate(1000%);
}
.zoomtop {
-webkit-transform:translate(0, -1000%);
-moz-transform:translate(0, -1000%);
-ms-transform:translate(0, -1000%);
-o-transform:translate(0, -1000%);
transform:translate(0, -1000%);
}
.zoombottom {
-webkit-transform:translate(0, 1000%);
-moz-transform:translate(0, 1000%);
-ms-transform:translate(0, 1000%);
-o-transform:translate(0, 1000%);
transform:translate(0, 1000%);
}
div.d1 {
width: 50%;
top: 0;
left: 0;
}
div.d2 {
width: 50%;
top: 0;
left: 50%;
}
div.d3 {
width: 25%;
top: 25%;
left: 0;
}
div.d4 {
width: 25%;
top: 25%;
left: 25%;
}
div.d5 {
width: 25%;
top: 25%;
left: 50%;
}
div.d6 {
width: 25%;
top: 25%;
left: 75%;
}
div.d7 {
width: 50%;
top: 50%;
left: 0;
}
div.d8 {
width: 50%;
top: 50%;
left: 50%;
}
div.d9 {
width: 50%;
top: 75%;
left: 0;
}
div.d10 {
width: 50%;
top: 75%;
left: 50%;
}
Thanks everyone,
Dave
Fortunately, since everything is fluid according to the viewport, you can still use percentages in the transform. See my Fiddle - http://jsfiddle.net/K3uPY/23/
One thing I did have to change was make sure #container was in the absolute center. I have also drastically simplified the JS and moved all of the positioning into the CSS.
HTML
<div id="wrapper">
<button id="movebtn">Move</button>
<div id="container">
<div class="box d1 active">1</div>
<div class="box d2 active">2</div>
<div class="box d3 active">3</div>
<div class="box d4 active">4</div>
<div class="box d5 active">5</div>
<div class="box d6 active">6</div>
<div class="box d7 active">7</div>
<div class="box d8 active">8</div>
<div class="box d9 active">9</div>
<div class="box d10 active">10</div>
</div>
</div>
JAVASCRIPT
$( "#movebtn" ).on('click', function() {
$('.box').toggleClass('active');
});
CSS
html,
body {
height:100%;
margin:0;
overflow: hidden;
width: 100%;
}
#wrapper {
height: 100%;
overflow: hidden;
width: 100%;
}
#container {
width: 50%;
height: 50%;
margin: auto;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.box {
background-color: red;
border: 2px solid #000000;
box-sizing: border-box;
cursor: pointer;
height: 25%;
position: absolute;
transition-duration: 600ms;
}
.box.active {
transform: none;
}
.d1 {
width: 50%;
top: 0;
left: 0;
transform: translateY(-300%);
}
.d2 {
width: 50%;
top: 0;
left: 50%;
transform: translateY(-300%);
}
.d3 {
width: 25%;
top: 25%;
left: 0;
transform: translateX(-300%);
}
.d4 {
width: 25%;
top: 25%;
left: 25%;
transform: translateX(-400%);
}
.d5 {
width: 25%;
top: 25%;
left: 50%;
transform: translateX(400%);
}
.d6 {
width: 25%;
top: 25%;
left: 75%;
transform: translateX(300%);
}
.d7 {
width: 50%;
top: 50%;
left: 0;
transform: translateX(-200%);
}
.d8 {
width: 50%;
top: 50%;
left: 50%;
transform: translateX(200%);
}
.d9 {
width: 50%;
top: 75%;
left: 0;
transform: translateY(300%);
}
.d10 {
width: 50%;
top: 75%;
left: 50%;
transform: translateY(300%);
}

Resources