CSS hardware accelerated width? - javascript

I am attempting to build a Phonegap app that will allow the user to change the size of a two column layout by moving the middle divider.
I was able to get this working, but there is a huge UX problem: it's laggy. It's not terrible, but on the latest iPad it's even noticeable, which has me worrying.
Here's my JS that does the resizing:
$("div").on("touchmove", "#columnResizeIcon", function(e) {
e.preventDefault();
var left = e.originalEvent.touches[0].pageX;
var right = $("#columnContainer").width() - left;
$("#leftColumn").css({
"width":left - 1 + "px",
"right":"auto",
});
$("#rightColumn").css({
"width":right - 1 + "px",
"left":"auto",
});
$("#columnResize").css({
"-webkit-transform":"translate3d(" + left + "px" + ", 0, 0)",
"left":"auto",
});
$("#columnResizeIcon").css({
"-webkit-transform":"translate3d(" + left + "px" + ", 0, 0)",
"left":"auto",
});
});
You'll notice that I take advantage of translate3d() to change the "left" value of the elements, as that is hardware accelerated. I believe the lag is being produced from changing the widths of the left and right column, which is what I need to be hardware accelerated.
A possible solution that I thought might work would be to use -webkit-transform:translate3d(50%, 0, 0) to push the right column over half the page, and then just changing that value, hoping that it would only stretch until it reached the parent. It continues, however, and goes 50% of the page, not 50% of the parent.
My HTML markup looks like this:
<div id="columnContainer">
<div id="columnResize"></div>
<div id="columnResizeIcon"></div>
<div id="leftColumn">
<div class="header">Left Header</div>
<div class="content"></div>
</div>
<div id="rightColumn">
<div class="header">Right Header</div>
<div class="content"></div>
</div>
</div>
And my CSS:
body{
background-color:#000;
}
#columnContainer{
position: absolute;
bottom:0;
top:0;
right:0;
left:0;
background-color:#000;
}
#leftColumn{
position: absolute;
top:0;
left:0;
right:50%;
bottom:0;
-webkit-overflow-scrolling: touch;
z-index: 1;
margin-right: 1px;
}
#rightColumn{
position: absolute;
top:0;
left:50%;
right:0;
bottom:0;
-webkit-overflow-scrolling: touch;
z-index: 1;
margin-left: 1px;
}
.header{
position: absolute;
left:0;
right:0;
height:33px;
z-index: 5;
background: -webkit-linear-gradient(top, #f4f5f7 0%,#a7abb7 100%);
box-shadow: inset 0 1px 0 #fff, inset 0 -1px 0 #7A8090, 3px 0 2px rgba(0,0,0,.3);
border-top-left-radius: 5px;
border-top-right-radius: 5px;
font-size: 17px;
font-family: Helvetica;
font-weight: bold;
letter-spacing: .2px;
text-align: center;
padding-top:9px;
color:#71787F;
text-shadow: 0 1px 0 #E3E5E9;
}
.content{
position: absolute;
left:0;
right: 0;
top:42px;
bottom: 0;
}
#leftColumn .content{
background-color:#F5F5F5;
}
#rightColumn .content{
background-color:#fff;
}
#columnResize{
position: absolute;
width:2px;
top:0;
bottom: 0;
left:50%;
margin-left:-1px;
background-color:#000;
z-index: 2;
}
#columnResizeIcon{
position: absolute;
z-index: 3;
width:10px;
height:30px;
top:50%;
bottom:50%;
margin-top:-15px;
left:50%;
margin-left:-7px;
border-left:2px solid #000;
border-right:2px solid #000;
}

I finally figured out a solution that works a lot better than what I had. Basically, I animate the container, and I hide the content when I'm resizing. Then, when the resizing is done, I show the content again. I used an animations to make it look pretty when hiding/showing. The code will explain it better than I will:
The almighty fiddle
1 http://jsfiddle.net/charlescarver/hnQHH/134/
My explanation
When the slider is tapped, it pushes all the text elements off the page with a translate3d() transform, then hides the div. This is because the lag returns if I try to update the width while the elements are shown. So, once the divs are hidden, I then just move the columns left or right with the translate3d() transform once again. I can do this without having the width of each element stop short because I set the left or right values to a value that can never be reached so it's extended far enough beyond the page. That way, I can simply shift it without worrying that it will cut off prematurely.
Weirdness
There are parts of this that are probably redundant, but I'll clean those up soon. You'll also probably notice some weird things going on, such as (1) cornerLeft, (2) dummy, (3) shadow, and in the JS, (4) minimum:
When I resize the page, the dummy nav bar extends the entire width of the left and right columns, which means it goes 1000% of the width. That means that I can't set a border-radius on the nav for the left and right sides of each column, as it would be so far off the screen that it wouldn't be visible. So, I made a simple corner to mask each side of the window, making it look pretty.
I hide .contentLeft and .contentRight when I resize as it causes lag when it's shown. I don't want to get rid of the nav bar though, so I make a dummy one that is always there on the page, and is simply revealed when the resize is about to happen. I think this reduces the lag as I don't have to add the element in, since it's always there.
One problem with that, however, is that when the normal nav overlays the dummy nav, the box-shadow's overlap, causing it to become darker for 200ms. I don't like this. So, I put in a shadow that is always on top of the nav, regardless of what nav is showing.
I can now easily set a bound that the draggable columns can reach before stopping. Convenient, right?
Code
HTML:
<div id="container">
<div class="cornerLeft"></div>
<div class="cornerRight"></div>
<div class="shadow"></div>
<div class="left">
<div class="contentLeft">
<div class="header"></div>
<div class="headerbehind"></div>
<div class="text textLeft">Praesent id metus massa, ut blandit odio. Proin quis tortor orci. Etiam at risus et justo dignissim congue. Donec congue lacinia dui, a porttitor lectus.</div>
</div>
<div class="dummy"></div>
<div class="dummybg"></div>
</div>
<div class="divider"></div>
<div class="right">
<div class="contentRight">
<div class="header"></div>
<div class="headerbehind"></div>
<div class="text textRight">Praesent id metus massa, ut blandit odio. Proin quis tortor orci. Etiam at risus et justo dignissim congue. Donec congue lacinia dui, a porttitor lectus.</div>
</div>
<div class="dummy"></div>
<div class="dummybg"></div>
</div>
</div>
CSS:
* {
-webkit-text-size-adjust:none;
}
#container {
position:fixed;
left:0;
right:0;
bottom:0;
top:0;
background-color:#000;
-webkit-transform: translateZ(0);
-webkit-perspective: 1000;
}
.left {
-webkit-transform:translate3d(0, 0, 0);
position:absolute;
left:-3000px;
right:50%;
top:0;
bottom:0;
border-right:1px solid #000;
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
.right {
-webkit-transform:translate3d(0, 0, 0);
position:absolute;
left:50%;
right:-3000px;
top:0;
bottom:0;
border-left:1px solid #000;
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
.divider {
width:24px;
height:40px;
border-left:2px solid #000;
border-right:2px solid #000;
position:absolute;
left:50%;
z-index:3;
margin-left:-14px;
margin-top:-20px;
top:50%;
-webkit-transform:translate3d(0, 0, 0);
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
-webkit-touch-callout: none;
-webkit-user-select: none;
}
.contentLeft {
position:absolute;
right:0;
bottom:0;
top:0;
-webkit-transform: translateZ(0);
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
.contentRight {
position:absolute;
left:0;
bottom:0;
top:0;
-webkit-transform: translateZ(0);
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
.cornerLeft:after {
content:"";
height:5px;
position:absolute;
left:0;
width:5px;
background: -webkit-linear-gradient(top, #F0F2F4 0%, #EAEBEE 100%);
z-index:700;
border-top-left-radius:5px;
box-shadow:inset 0 1px 0 #fff;
}
.cornerLeft {
position:absolute;
z-index:700;
left:0;
width:5px;
height:5px;
background-color:#000;
}
.cornerRight:after {
content:"";
height:5px;
position:absolute;
right:0;
width:5px;
background: -webkit-linear-gradient(top, #F0F2F4 0%, #EAEBEE 100%);
z-index:700;
border-top-right-radius:5px;
box-shadow:inset 0 1px 0 #fff;
}
.cornerRight {
position:absolute;
z-index:700;
right:0;
width:5px;
height:5px;
background-color:#000;
}
.header, .dummy {
position: absolute;
left:0;
right:0;
height:35px;
background: -webkit-linear-gradient(top, #f4f5f7 0%, #a7abb7 100%);
border-top-left-radius: 5px;
border-top-right-radius: 5px;
font-size: 17px;
font-family: Helvetica;
font-weight: bold;
letter-spacing: .2px;
text-align: center;
padding-top:9px;
color:#71787F;
text-shadow: 0 1px 0 #E3E5E9;
word-break: break-all;
box-shadow:inset 0 1px 0 #fff, inset 0 -1px 0 #7A8090;
}
.shadow {
height:44px;
position:absolute;
left:0;
right:0;
box-shadow:0 1px 2px rgba(0, 0, 0, .2);
z-index:600;
}
.header {
z-index:500;
}
.dummy {
z-index:100;
}
.headerbehind {
position:absolute;
background-color:#000;
left:0;
right:0;
height:44px;
z-index:499;
}
.text, .dummybg {
margin-top:44px;
background-color:#fff;
position:absolute;
top:0;
right:0;
left:0;
bottom:0;
}
.text {
z-index:2;
padding:20px 40px;
-webkit-animation-duration:200ms;
-webkit-animation-timing-function:ease;
}
.contentLeft, .contentRight {
z-index:300;
}
.leftOut {
-webkit-transform:translate3d(-100%, 0, 0);
-webkit-animation-name:leftOut;
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
.leftIn {
-webkit-transform:translate3d(0, 0, 0);
-webkit-animation-name:leftIn;
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
#-webkit-keyframes leftOut {
0% {
-webkit-transform:translate3d(0, 0, 0);
}
100% {
-webkit-transform:translate3d(-100%, 0, 0);
}
}
#-webkit-keyframes leftIn {
0% {
-webkit-transform:translate3d(-100%, 0, 0);
}
100% {
-webkit-transform:translate3d(0, 0, 0);
}
}
.rightOut {
-webkit-transform:translate3d(100%, 0, 0);
-webkit-animation-name:rightOut;
}
.rightIn {
-webkit-transform:translate3d(0, 0, 0);
-webkit-animation-name:rightIn;
}
#-webkit-keyframes rightOut {
0% {
-webkit-transform:translate3d(0, 0, 0);
}
100% {
-webkit-transform:translate3d(100%, 0, 0);
}
}
#-webkit-keyframes rightIn {
0% {
-webkit-transform:translate3d(100%, 0, 0);
}
100% {
-webkit-transform:translate3d(0, 0, 0);
}
}
JS:
minimum = 100;
$(".contentLeft").css("width", ($("#container").width() / 2) - 1);
$(".contentRight").css("width", ($("#container").width() / 2) - 1);
$("div").on("touchstart", ".divider", function (e) {
$(".textLeft").removeClass("leftIn");
$(".textLeft").addClass("leftOut");
$(".textRight").removeClass("rightIn");
$(".textRight").addClass("rightOut");
setTimeout(function () {
$(".contentLeft, .contentRight").hide();
}, 200);
});
$("div").on("touchmove", ".divider", function (e) {
e.preventDefault();
if ($(".contentLeft").css("display", "none")) {
var page = $("#container").width();
var left = e.originalEvent.touches[0].pageX;
var right = page - left;
updateWidth(page, left, right);
}
});
//$(".contentLeft, .contentRight").hide();
$("div").on("touchend", ".divider", function (e) {
setTimeout(function () {
$(".textLeft").removeClass("leftOut");
$(".textLeft").addClass("leftIn");
$(".textRight").removeClass("rightOut");
$(".textRight").addClass("rightIn");
$(".contentLeft, .contentRight").show();
}, 200);
});
$(window).on('orientationchange', function (e) {
var page = $("#container").width();
var leftWidth = $(".contentLeft").width();
var rightWidth = $(".contentRight").width();
var previousWidth = (leftWidth + rightWidth);
if (leftWidth + rightWidth + 2 < page) {
var left = (page / 2) - (previousWidth / 2) + leftWidth;
} else if (leftWidth + rightWidth + 2 > page) {
var left = leftWidth - ((previousWidth / 2) - (page / 2));
}
var right = page - left;
updateWidth(page, left, right);
});
function updateWidth(page, left, right) {
if (left < minimum) {
var finalLeft = minimum;
var finalRight = (-1 * (page - minimum));
var finalRightWidth = (page - minimum);
} else if (right < minimum) {
var finalLeft = (page - minimum);
var finalRight = (-1 * minimum);
var finalRightWidth = minimum;
} else {
var finalLeft = (left);
var finalRight = (0 - right);
var finalRightWidth = (right);
}
$(".divider").css({
"-webkit-transform": "translate3d(" + finalLeft + "px, 0, 0)",
"left": "auto",
});
$(".left").css({
"-webkit-transform": "translate3d(" + finalLeft + "px, 0, 0)",
"right": "100%",
});
$(".right").css({
"-webkit-transform": "translate3d(" + finalRight + "px, 0, 0)",
"left": "100%",
});
$(".contentLeft").css("width", finalLeft);
$(".contentRight").css("width", finalRightWidth);
}
1 Yes, it took me 134 tries.

I had some success by pushing the two elements into question in the hardware-accelerated stack:
#leftColumn,
#rightColumn {
-webkit-transform: translate3d(0,0,0);
}
Seems to be resizing much more smoothly. It's not that changing width itself is optimized, rather the elements themselves are re-rendered much more quickly.
I set up a plunk here: http://plnkr.co/edit/5RMtCl1Sql8f3CmQLHFz

Related

How to create a separation animation in CSS upon hover of a picture?

I have the picture below to which I would like to animate a diagonal split from the line cut through the logo from the top left to bottom right as shown below. The animation would split the picture on the X axis a few pixels apart.
https://i.ibb.co/fDzZ6Sc/Logo.png
I have made some progress so far, I used the same picture twice and laid them over each other and skewed on the X axis. However this split the picture apart from the top right to bottom left. I like it the other way around and can't figure it out.
I also could not figure out how to hover over the whole picture for the animation to execute for both of the sides.
body { background: gainsboro; }
.pageOption {
overflow: hidden;
position: relative;
margin: 0 auto;
width: 40em; height: 27em;
}
.option, .option img { width: 100%; height: 100%; }
.option {
overflow: hidden;
position: absolute;
/* arctan(27 / 40) = 34.01935deg
* need to skew by 90deg - 34.01935deg = 55.98065deg
*/
transform: skewX(-55.98deg);
}
.option:first-child {
left: -.25em;
transform-origin: 100% 0;
}
.option:last-child {
right: -.25em;
transform-origin: 0 100%;
}
.option img, .option:after {
transform: skewX(55.98deg);
transform-origin: inherit;
}
.option:hover {
left: -.8em;
transition: 1s;
}
<div class='pageOption'>
<a href='#' class='option'>
<img src='https://i.ibb.co/fDzZ6Sc/Logo.png'>
</a>
<a href='#' class='option'>
<img src='https://i.ibb.co/fDzZ6Sc/Logo.png'>
</a>
</div>
Essentially what I would like to happen is upon hovering on the whole picture, the two sides would split from the middle (cut from the line going from top left to bottom right), and when you move your mouse off, for the image to go back together.
You can consider clip-path and easily do this like below. The trick is to use two opposite polygon where the combination will make the full image.
.image {
width:340px;
height:230px;
background-image:url(https://i.ibb.co/fDzZ6Sc/Logo.png);
background-size:0;
position:relative;
}
.image:before,
.image:after {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
background-image:inherit;
background-size:cover;
transition:1s;
}
.image:before {
clip-path:polygon(0 0, 15% 0, 97% 100%, 0 100%);
}
.image:after {
clip-path:polygon(100% 0, 15% 0, 97% 100%);
}
.image:hover::before{
transform:translate(-20px,-10px);
}
.image:hover::after{
transform:translate(20px,10px);
}
body {
background:pink;
}
<div class="image">
</div>
If you don't want to cut the The adjust the clip-path
.image {
width:340px;
height:230px;
background-image:url(https://i.ibb.co/fDzZ6Sc/Logo.png);
background-size:0;
position:relative;
}
.image:before,
.image:after {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
background-image:inherit;
background-size:cover;
transition:1s;
}
.image:before {
clip-path:polygon(0 0, 32% 0 ,32% 19%, 97% 100%, 0 100%);
}
.image:after {
clip-path:polygon(100% 0,32% 0,32% 19%,97% 100%);
}
.image:hover::before{
transform:translate(-20px,-10px);
}
.image:hover::after{
transform:translate(20px,10px);
}
body {
background:pink;
}
<div class="image">
</div>

increment/decrement transform rotation not working fiddle jquery

I'm working on this pie chart...
Anytime I click on red...the rounded absolute-positioned red div rotates an angles lower than 180 degrees to complete the another half according to the votes numbers...making the pie simulating this color correspond to the percentage of red votes.
PROBLEM
When I click on the red button the red div rotates correctly, but when clicking on the bue...it doesnt....
I'm currently testing the red size....so I want to make this work when the red sslice is 50% or greater (till 100%) out of the total size, once this works well it'll be added a blue positioned div to make the same for the blue side...
What am I doing wrong?
var red=0;
var blue=0;
var Psum = (red+blue);
var r_rotation = 0;
var red_rotacion_control= 0;
$(".VoteMain").on("click",function(){
if($(this).hasClass("VoteRed")){
red++;
Psum = (red+blue);
red_size_control = "increase_red";
}
if($(this).hasClass("VoteBlue")){
blue++;
Psum = (red+blue);
red_size_control = "decrease_red";
}
var red_percentage= Math.floor((red/Psum)*100);
var blue_percentage= 100-red_percentage;
///old +- new angles?
var sum_rotacion = (1/(Psum-1) + 1/Psum)*360;
var rest_rotacion = (1/(Psum-1) - 1/Psum)*360;
//display percentages
$(".VoteRed span").text(red_percentage+"% :" +red+" votes > Votos Totales "+Psum);
$(".VoteBlue span").text(blue_percentage+"% :"+blue);
//rotate pieChart
if(red> blue){
//red mayor
$(".red").css('z-index', 3000);
$(".blue").css('z-index', 1);
if(red==Psum){
$(".red").rotate(180);
}else{
if(red_size_control=="increase_red"){
r_rotacion=(180-sum_rotacion);
}else if(red_size_control=="decrease_red"){
r_rotacion=(180-rest_rotacion);
}
$(".red").rotate(r_rotacion);
}
}
});
//function
jQuery.fn.rotate = function(degrees) {
$(this).css({'transform' : 'rotate('+ degrees +'deg)'});
return $(this);
};
.pie_container{
margin:40px;
}
.pie{
position:relative;
height:100px;
width:100px;
qbackground:yellow;
border-radius:50%;
background-image:linear-gradient(to right, blue 50%, red 0);
transform-origin: 50% 50%;
}
.blue{
position:absolute;
top:0;
left:0;
height:100px;
width:50px;
background:blue;
qborder:1px solid green;
border-top-left-radius: 50px;
border-bottom-left-radius: 50px;
transform-origin: 100% 50%;
transform: rotate(0deg);
}
.red{
position:absolute;
top:0;
right:0;
height:100px;
width:50px;
background:red;
border:1px solid yellow;
border-top-right-radius: 50px;
border-bottom-right-radius: 50px;
transform-origin: 0% 50%;
transform: rotate(0deg);
transition:all 1s ease-out;
}
.red span{
position:absolute;
bottom:0;
left:20px;
}
.VoteMain{cursor:pointer;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="pie_container">
<div class="pie">
<div class="red"><span>b</span></div>
</div>
<div class="PollVoteMain">
<div class="VoteMain VoteBlue"><button>blue</button> <span>0</span></div>
<div class="VoteMain VoteRed"><button>red</button> <span>0</span></div>
</div>
</div>
You have to change the whole rotate calculation part to:
r_rotacion = (red_percentage / 100) * 360 - 180;
$(".red").rotate(r_rotacion);
The rotate is absolute not relative to the previous state
Here is a working jsfiddle

How do I animate div with background image along curved path but stop at X percentage

I have been able to animate a div with a background image as well as resize it along the path. However, I am trying to get this CSS-based animation to stop at a certain percentage of the progress.
The premise is to visually show a student her/his progress of completing a varying number of tasks (8 of 12 complete. 68%). That is not a problem with a straight progress bar, but I am looking to use an image of a mountain with a hiker moving along a path. I can get the hiker image from start to end with the following code, but I need it to stop based on the progress of the student.
I am trying to keep this as simple as I can, but do not have to use CSS.
.mtnBg
{
height:306px;
width:450px;
border:1px silver solid;
background-image: url(https://comps.canstockphoto.com/mountain-with-trail-and-sun-retro-style-eps-vector_csp43572145.jpg);
background-repeat: no-repeat;
background-size: 100%;
display:block;
opacity:.18;
z-index:-1;
}
.animSurround {
margin:0;
padding:0;
height:32px;
width:32px;
display:block;
position:relative;
left:140px;
bottom:50px;
border:1px none black;
animation: yAxis 2.8s 1 ease;
}
.anim {
background-image: url(https://www.tenstickers.co.uk/wall-stickers/img/preview/hiker-icon-sticker-8451.png);
background-repeat: no-repeat;
min-height:32px;
min-width:32px;
background-size: 100%;
animation-iteration-count:1;
animation: zoom-move 2.8s ease 1;
animation-fill-mode: forwards;
}
.anim::after {
/* Render dot, and animate along Y-axis */
min-height:96px;
min-width:96px;
}
#keyframes zoom-move {
0% {
transform: scale(3) translateX(calc(0px)) translateY(0px);
opacity: 0.50;
border-radius:32px;
background-color: rgba(256 , 256, 256, 1);
}
25% {
transform: scale(2.6) translateX(60px) translateY(-19px);
opacity: 1;
border-radius:32px;
background-color: rgba(256 , 256, 256, 1);
}
50% {
transform: scale(1.7) translateX(68px) translateY(-50px);
opacity: 1;
border-radius:32px;
background-color: rgba(256 , 256, 256, 1);
animation-play-state: paused;
}
93% {
background-color: rgba(256 , 256, 256, 1);
}
99% {
transform: scale(1.1) translateX(161px) translateY(-122px);
opacity: 1;
border-radius:32px;
background-color: rgba(76, 175, 80, 1);
}
100% {
transform: scale(1.1) translateX(161px) translateY(-122px);
opacity: 1;
border-radius:32px;
background-color: rgba(76, 175, 80, 1);
}
}
<div class="mtnBg"></div>
<div class="animSurround">
<div class="anim"></div>
</div>
Any help would be appreciated.
You can rely on the animation-play-state property. The is idea to convert the % value to the time when the animation should be paused. So you using JS/jQuery you run the animation and after this amount of time you set the property animation-play-state:
Here is an example with a simplied animation:
/* if we want the animation to run until 10%
we consider a duratioon of Xs and we should run until 0.1 * Xs
The duration will only affect the speed
so use a small value to simulate an instant change.
*/
var duration = 3;
function stop_animation(element, percent) {
var stop = (percent / 100) * duration; /* we get the value un second*/
stop *= 1000 /* we transform to milliseconds */
element.css('animation', 'anim ' + duration + 's linear');
setTimeout(function() {
element.css('animation-play-state', 'paused');
}, stop);
}
stop_animation($('.element').eq(0),50);
stop_animation($('.element').eq(1),20);
.container {
width: 200px;
height: 50px;
border: 1px solid;
border-left: 0;
background: linear-gradient(to right, #000 10%, transparent 11%) 0 0/20px 100%;
}
.element {
height: 100%;
width: 20px;
margin-left: 0;
background: red;
}
#keyframes anim {
from {
margin-left: 0;
}
to {
margin-left: calc(100% - 20px);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="element"></div>
</div>
<div class="container">
<div class="element"></div>
</div>

CSS menu not pushing in

I have two push menu's: left and right. The right push menu is not working correctly when viewed on a mobile (issue 1 below). Additionally, neither menu's work in IE 11 (issue 2 below).
Mobile - On a mobile, when you open the left push menu and then
close it the right menu pushes into view and you cannot get rid of
it.
IE issue - In IE 11 the push menus do not appear, with the cause, as
far as I can tell, being: position:fixed; as applied to
menu-push-left and menu-push-right elements. I originally had
position:absolute; but this would cause the menu-push-right element
to just appear when opened in IE instead of "sliding" in. I have no
idea why the position:fixed; does not work in this instance of IE.
IE 7+, last I knew, supports position:fixed;
Could someone take a look at my code and tell me what I may have missed?
The JsFiddle is here: http://jsfiddle.net/totaleeyou/0w5w4t4s/8/
body {
color:#2c2c2c;
background-color:#ffffff;
padding:0;
margin:0;
font-size:1em;
font-family:Arial, Helvetica, sans-serif;
overflow-x:hidden;
}
body.has-active-menu-push-left,
body.has-active-menu-push-right {
overflow:hidden;
}
body, header.scroll, header ul.logo, #menu-push-left, #menu-push-right, button.menu-close i.fa-times-circle-o, .page-masking {
-webkit-transition:all 0.5s;
-moz-transition:all 0.5s;
-ms-transition:all 0.5s;
-o-transition:all 0.5s;
transition: all 0.5s;
}
body.has-active-menu-push-left, #menu-push-left {
-webkit-transform:translate(100%, 0);
-moz-transform:translate(100%, 0);
-ms-transform:translate(100%, 0);
-o-transform:translate(100%, 0);
transform:translate(100%, 0);
}
body.has-active-menu-push-right, #menu-push-right {
-webkit-transform:translate(-100%, 0);
-moz-transform:translate(-100%, 0);
-ms-transform:translate(-100%, 0);
-o-transform:translate(-100%, 0);
transform:translate(-100%, 0);
}
#media only screen and (min-width:780px) {
body.has-active-menu-push-left, #menu-push-left {
-webkit-transform:translate(500px, 0);
-moz-transform:translate(500px, 0);
-ms-transform:translate(500px, 0);
-o-transform:translate(500px, 0);
transform:translate(500px, 0);
}
body.has-active-menu-push-right, #menu-push-right {
-webkit-transform:translate(-500px, 0);
-moz-transform:translate(-500px, 0);
-ms-transform:translate(-500px, 0);
-o-transform:translate(-500px, 0);
transform:translate(-500px, 0);
}
}
.wrapper {
width:100%;
padding:0;
position:relative;
}
#media only screen and (min-width:780px) {
.wrapper {
width:1000px;
margin:0 auto;
padding: 0 5px;
}
}
#page-masking {
position:fixed;
}
.page-mask {
z-index:100;
top:0;
left:0;
width:0;
height:0;
background-color:#bec4a6;
}
.page-mask.is-active {
width:100%;
height:100vh;
opacity:.7;
-webkit-transition:opacity .5s;
transition:opacity .5s;
}
.close-container {
width:100%;
height:55px;
padding:5px;
position:relative;
}
button.menu-close {
color:#fdbc5d;
text-decoration:none;
font-size:3em;
position:absolute;
top:5px;
right:25px;
display:block;
border:none;
background:none;
}
#menu-push-left,
#menu-push-right {
position:fixed;
top:0;
width:100%;
height:100vh;
z-index:150;
overflow-x:hidden;
overflow-y:auto;
background-color:#0079c1;
}
#menu-push-left {
left:-200%;
}
#menu-push-right {
right:-200%;
}
#media only screen and (min-width:780px) {
#menu-push-left {
width:500px;
left:-1000px;
}
#menu-push-right {
width:500px;
right:-1000px;
}
}
I changed the position of your menues to 'fixed', and that seemed to do the trick =)
#menu-push-left, #menu-push-right {
position: fixed;
top: 0;
width: 100%;
height: 100vh;
z-index: 150;
overflow-x: hidden;
overflow-y: auto;
background-color: #0079c1;
}

Html: scrollable div with fixed background

I'm trying to get a full-screen image background with a scrollable div on its center, so I wrote this code
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Bio</title>
<link href="../css/layout-base.css" rel="stylesheet">
<script type="text/javascript" src="../jquery/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
$(window).ready(function(){
var background = $('#background');
var scrollable = $('#scrollable-container');
var halfWhite = $('#halfWhite');
var halfBlack = $('#halfBlack');
/* calcolo dimensione finestra */
var maxWidth = $(window).width();
var maxHeight = $(window).height();
/* settaggio dimensioni immagine sfondo */
background.css("height",maxHeight);
background.css("width",maxWidth);
scrollable.css("height",maxHeight);
/* settaggio dimensioni riempimento sfondo */
halfWhite.css("height",maxHeight);
halfWhite.css("width",maxWidth/2);
halfBlack.css("height",maxHeight);
halfBlack.css("width",maxWidth/2);
});
$(window).resize(function(){
var background = $('#background');
var scrollable = $('#scrollable-container');
var halfWhite = $('#halfWhite');
var halfBlack = $('#halfBlack');
/* calcolo dimensione finestra */
var maxWidth = $(window).width();
var maxHeight = $(window).height();
/* settaggio dimensioni immagine sfondo */
background.css("height",maxHeight);
background.css("width",maxWidth);
scrollable.css("height",maxHeight);
/* settaggio dimensioni riempimento sfondo */
halfWhite.css("height",maxHeight);
halfWhite.css("width",maxWidth/2);
halfBlack.css("height",maxHeight);
halfBlack.css("width",maxWidth/2);
});
</script>
</head>
<body>
<div id="background">
<div id="halfWhite"></div>
<div id="halfBlack"></div>
<div id="scrollable-container">
<div class="content">
<div id="text"></div>
<img src="../media/index/tasto1.png"/>
<img src="../media/index/tasto2.png"/>
<img src="../media/index/tasto3.png"/>
<img src="../media/index/tasto4.png"/>
</div><!--div content -->
</div>
</div><!-- div background -->
</body>
</html>
With the relative css:
body{
overflow:hidden;
margin:0!important;
}
#background{
background-image:url(../media/index/back.png);
background-size:contain;
background-position:center;
background-repeat:no-repeat;
}
#halfWhite{
position:relative;
background-color: white;
z-index: -10;
float: left;
}
#halfBlack{
position:relative;
background-color: black;
z-index: -10;
float: right;
}
#scrollable-container{margin-left: 15%;margin-right: 15%;background- color:rgba(0,0,0,0.00);}
.content{
height:98%;
position: relative;
top:1%;
padding-left: 15%;
padding-right: 15%;
box-shadow: -10px 2px 15px #dedede,10px -2px 15px #dedede;
-moz-box-shadow:-10px 2px 15px #dedede,10px -2px 15px #dedede;
-webkit-box-shadow:-10px 2px 15px #dedede,10px -2px 15px #dedede;
background-color:rgba(255,255,255,0.8);
}
#text{position:absolute;top:10%;width:100%;height:100000px;width:70%}
.menu{
width:15%;
-webkit-transition: all 0.4s linear;
-moz-transition: all 0.4s linear;
-o-transition: all 0.4s linear;
-ms-transition: all 0.4s linear;
transition: all 0.4s linear;
}
.menu:hover{
-webkit-transform: scale(0.85,0.85);
-moz-transform: scale(0.85,0.85);
-o-transform: scale(0.85,0.85);
-ms-transform: scale(0.85,0.85);
transform: scale(0.85,0.85);
}
.menu img{width:100%}
#home{position:absolute;top:0px;left:0px;}
#events{position:absolute;top:0px;right:0px;}
#gallery{position:absolute;bottom:0px;left:0px;}
#disco{position:absolute;bottom:0px;right:0px;}
I want the #text div to scroll while the rest of the page has to stay fixed (so that the background is always on the same position), but when I add overflow property to the parent divs there are strange side effects (for example, the .content div goes to the very bottom of the page).
How can I achieve this behaviour? Is this the correct way to make this kind of layout?
make this #text div style="position:fixed" and the rest parts with position:absolute.
You need to place your background first in your html and give it a property of position: fixed. Then the rest of your html needs to go on top without the fixed property.

Categories