I am currently working on making a flipping animation on some divs.
However, I have found that it works incorrectly and differently in every browser that I have tried. Only Edge works the way that I want.
I want clicking the "flip" text to flip over in order to show the .flipping-view-back div, and hide the .flipping-view-front div. Additionally, the toolbar with position:fixed on the back div should be fixed at the top of the page even when scrolling.
In reality, this is only working in some browsers.
On Edge: This is working exactly how I want it to. Video
On Chrome: The front div flips over, but there is no back div visible behind it. The back div only pops in once the rotation transition has fully completed. Strangely, scrolling at any time during the flip will also trigger the back div to pop in. Also, scrolling down moves the fixed div out of sight. Video
On iOS Safari: This flips correctly, but scrolling down moves the fixed div out of sight. Video
In all these videos, I clicked on the flip text and waited for the animation to finish. Then I scrolled down.
How can I make the flip animation correct and keep the fixed div at the top in all browsers?
var currView = 0;
const rotatingViewElem = document.querySelector(".main");
const VIEW_FEED = 0;
const VIEW_FLIPPING_SEND = 1;
var viewFeedElem = document.querySelector(".view-positioner.feed");
var viewCreateElem = document.querySelector(".view-positioner.create");
var viewSelectRecipientsElem = document.querySelector(".view-positioner.select-recipients");
var viewFlippingSendElem = document.querySelector(".view-positioner.flipping-send");
var viewsList = [viewFlippingSendElem];
function flipView(isGoForward) {
var flippingElem = viewsList[currView];
var globalRotate;
if (isGoForward) {
globalRotate = "rotateY(180deg)";//flip around
} else {
globalRotate = "rotateY(0deg)";
}
flippingElem.style.transform = globalRotate;
}
document.querySelector(".create-send-button").addEventListener("click", function (e) { flipView(true) })
body, html{
width:100%;
height:100%;
margin:0px;
overflow:hidden;
}
.main{
perspective: 2000px;
height:100%;
}
.flipping-view-wrapper{
transform: rotateY(0);
transform-style: preserve-3d;
transition: transform 5.5s;
}
body{
height: 100%;
}
.view{
transform-style: preserve-3d;
position: relative;
padding-top:1px;
overflow-y:auto;
height: calc(100% - 1px);
width:100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.view-positioner{
position: absolute;
left:0px;
top:0px;
width:100%;
height:100%;
}
.flipping-view-front{
background-color: pink;
transform: rotateY(0deg);
}
.flipping-view-back{
background-color: green;
transform:rotateY(180deg);
}
.create-send-button{
cursor: pointer;
}
/* begin top toolbar */
.top-toolbar{
position:fixed;
top:0px;
left:0px;
width:100%;
height:55px;
background:#FFFB00;
}
<!DOCTYPE html>
<html>
<body class="lightblue">
<div class="main">
<div class="view-positioner flipping-send flipping-view-wrapper lightblue ">
<div class="view-positioner view create flipping-view-front">
<div class="create-inputs center">
<div class="create-send-button" style="font-size: 50px;">
flip to the backside this is long so you can see
</div>
</div>
</div>
<div class="view-positioner view select-recipients lightblue flipping-view-back">
<div class="top-toolbar">
fixed
</div>
<div style="width:10px">Long text a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a</div>
</div>
</div>
</div>
</body>
</html>
Could have something to do with the browsers itself, maybe look into -webkit. There are webkits for different browser so you might need to use multiple webkits for different browsers
What is WebKit and how is it related to CSS?
That post might give you some more info
Related
I am trying to construct a simple timeline event div in HTML/CSS. It's basically just a colored rectangle with some text inside (a title). The timeline scrolls horizontally.
The thing that I don't seem to be able to figure out is how to keep the title of the event div in view when the timeline is scrolled. I would like the title to move all the way to the right and even outside the container so that it stays visible as long as the container div is in view. Is that possible at all in CSS?
This is what I have so far:
<html>
<style>
.dummy_timeline {
width:5000px;
top:0px;
left:0px;
height:20px;
background: linear-gradient(90deg, #222 1%, transparent 1%) 1px 0, #fff;
background-size: 200px 1px;
}
.container {
overflow: visible;
position:absolute;
background:#eee;
border:1px solid black;
width:200px;
height:50px;}
.title {
position: absolute;
left:0;
}
</style>
<body>
<!-- JUST A TIMELINE PLACEHOLDER SO THAT THE VIEW CAN SCROLL -->
<div class='dummy_timeline'></div>
<!-- EVENT 1 -->
<div class='container' style='left:120px; top:40;'>
<div class='title'>TITLE1</div>
</div>
<!-- EVENT 2 -->
<div class='container' style='left:50px; top:140;'>
<div class='title'>TITLE2</div>
</div>
</body>
</html>
What I need to happen is this:
(1) When the div is completely in view the title stays in its default position
OUTSIDE THE VIEW | IN VIEW
|
| [----------------]
| [ TITLE2 ]
| [----------------]
|
(2) When srolling, the title starts moving to the right to stay visible
OUTSIDE THE VIEW | IN VIEW
|
|---------]
| TITLE2 ]
|---------]
|
(3) When srolling even more, the title moves out of its container and stays in view until the container has completely disappeared
OUTSIDE THE VIEW | IN VIEW
|
|-]
| ]TITLE2
|-]
|
| = the left-most side of the browser window
Pure CSS
Salman A suggested that I would change the requirements as to not to allow the right edge of the title go past the right edge of its parent. The pure CSS solution, as suggested by Salman A, would be simply to change the CSS for the title element to read:
.title {
display: inline-block;
position: sticky;
left: 0;
}
This may even be the desired behavior so I'm inclined to change my requirements.
JavaScript
For future reference, I'm also enclosing the JavaScript solution I found by following the link (How can I tell if a DOM element is visible in the current viewport?) found in the comment by B001ᛦ, which, in turn, lead me to a post by www139. I adapted the code provided by www139 to check the horizontal positions of elements and, when needed, to adjust the padding of the title to keep it in view. This version allows the title to go past the right edge of its parent. The gist is in the <script> section.
<html>
<style>
.dummy_timeline {
width:5000px;
top:0px;
left:0px;
height:20px;
background: linear-gradient(90deg, #222 1%, transparent 1%) 1px 0, #fff;
background-size: 200px 1px;
}
.container {
overflow: visible;
position:absolute;
background:#eee;
border:1px solid black;
width:200px;
height:50px;}
.title {
position: absolute;
left:0;
}
</style>
<script>
window.onscroll = function() {
var elements = document.getElementsByClassName('container');
for (var i = 0; i != elements.length; i++) {
element = elements[i];
offsetLeft = element.getBoundingClientRect().left;
offsetRight = element.getBoundingClientRect().right;
span = element.getElementsByClassName('title')[0];
if (offsetRight <= 0) {
span.style.paddingLeft = 0;
} else if (offsetLeft <= 0) {
span.style.paddingLeft = -offsetLeft;
} else {
span.style.paddingLeft = 0;
}
}
};
</script>
<body>
<!-- JUST A TIMELINE PLACEHOLDER SO THAT THE VIEW CAN SCROLL -->
<div class='dummy_timeline'></div>
<!-- EVENT 1 -->
<div class='container' style='left:120px; top:40;'>
<span class='title'>TITLE1</span>
</div>
<!-- EVENT 2 -->
<div class='container' style='left:50px; top:140;'>
<span class='title'>TITLE2</span>
</div>
</body>
</html>
Is there any way to just change the colour of a scrollbar in CSS, but keep the native 'disappear when not scrolling' effect. Basically I just want to turn the native scrollbar blue instead of its default black/dark-grey, but whenever I apply code like this
::-webkit-scrollbar {
width:5px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: blue;
border-radius:5px;
opacity:0.5;
}
The scrollbar looks how I want it too, but its persistent, instead of disappearing when i'm not scrolling. Is there any way I can keep that effect on a custom scrollbar?
EDIT - As requested my current browser is google chrome 73.0.3683.103
The most you can do using only css and webkit is to use the :hover/:active selectors to display or hide the scrollbar. The thing is, this will work on hover/selection and not on a finger swipe or a mouse wheel. Also this webkit property will not work on firefox or edge.
::-webkit-scrollbar-thumb {
background: transparent;
border-radius: 5px;
opacity: 0;
}
::-webkit-scrollbar-thumb:hover {
background: blue;
border-radius: 5px;
opacity: 0.5;
}
Info on webkit scrollbar
This question has a nice example of a smooth transition on hover
A late answer hopefully it still helps.
I don't think you can do this with pure CSS, (but i could be wrong)
You can use some jQuery to help you. I have a working fiddle here: https://jsfiddle.net/kingafrojoe/Le253gdw/29/
In your CSS .has-scroll to the scrollbar selectors as below
/* Add a css class to your scroll selectors */
.has-scroll::-webkit-scrollbar {
width: 15px;
}
.has-scroll::-webkit-scrollbar-track {
background: transparent;
}
.has-scroll::-webkit-scrollbar-thumb {
background: blue;
border-radius: 5px;
opacity: 0.5;
}
#tall {
height: 500px;
width: 100%;
background: #00ffff;
display: block;
}
In your HTML you will need a wrapper div wrapping the whole body of your document.
The body class also gets the class has-scroll jQuery will control this class.
<body class="has-scroll">
<div id="site">
<div id="tall"> I am tall content</div>
<!-- ALL other page HTML -->
</div>
</body>
</html>
Then some jQuery to detect the height of the content and the window.
If the content is taller than the window then there needs to be a scrollbar, else the scrollbar can do default behavior
<script type="text/javascript">
jQuery(window).load(function(){
var _body = $('body');
var _site = $('#site');
$(window).resize(function(){
show_scroll();// call the function on the window resize
});
show_scroll();// call the function
function show_scroll(){
// if the content wrapper is taller than the window add the has-scroll class,
// else remove the has scroll class to return default scroll behavior.
if(_site.outerHeight()>$(window).outerHeight()){
_body.addClass('has-scroll');
}else{
_body.removeClass('has-scroll');
}
}
});
</script>
I use below mention code to produce a CSS transition effect.
A div shows first image (i.e. 1.jpg), and upon mouse-hover the second image (2.jpg) is appear through CSS transition and when mouse-out the first image is back to display.
I need a third image on mouse-out so kindly help me how i do this through CSS.
My coding is as under:
.mainimg
{
background-image:url(1.jpg);
height: 300px;
width: 300px;
transition: 1s;
}
.img2
{
background-image:url(2.jpg);
background-size:500px 500px;
width:0px;
height:300px;
transition:1s
}
.mainimg:hover .img2
{
width:300px;
transition:1s;
}
<div class="mainimg">
<div class="img2"></div>
</div>
Try this out: use the same div for containing image
<div class="mainimg">
and use css hover to change image background
.mainimg {
background-image:url(1.jpg);
height: 300px;
width: 300px;
transition: 1s;
}
.mainimg:hover {
background-image:url(2.jpg);
transition: 1s;
}
The rollover is state is binary in CSS, an element is either being hovered over or it is not. You will need to use JavaScript for doing what you want.
what #Franz Thüs says is correct you have to use Javascript for the 3e image.
also what #Med7at is saying try using one div and change the image via the :hover
this should work for you.
I used an id instead of an class so only one item will change with those images.
i used colors so you can see the differents.
var mouseOut = document.getElementById("mainimg");
mouseOut.onmouseout = function() {
this.style.backgroundColor = "orange"; //this.style.background = "url(3.jpg)"
}
#mainimg{
background:blue; /*background-image:url(1.jpg);*/
height: 300px;
width: 300px;
transition: 1s;
}
#mainimg:hover{
background:red; /*background-image:url(2.jpg);*/
background-size:500px 500px; /* this will make the 3 img look missplaced for 1 second.
}
<div id="mainimg"></div>
see the comments what you should put in that line to make it work with the images.
Interesting bug in Chrome. If a scrollable div is off screen when the page initially loads, then that scrollable div is not scrollable by way of mouse wheel or touch pad gestures until it is given focus (by double clicking somewhere within its element, or selecting text inside of it).
Update
This bug is documented here https://code.google.com/p/chromium/issues/detail?id=417345 It remains unfixed as of May 2015. The thread provides some interesting possible solutions with javascript, but I would like to see if anyone has any alternate suggestions for a fix, possibly not involving JS
The Bug
When you click on the button to "Show Side Container", the side container will slide into view, and the main container will slide out of view. If you immediately try to scroll using the mouse wheel or two finger gesture on a laptop track pad, nothing will happen. You can use page up and page down on the keyboard however, these do work. You can of course also use the actual scroll by by clicking on it with a mouse.
In firefox and IE, you can use the mouse wheel to scroll on this element
Example
http://codepen.io/msorrentino/full/aOYaOM/
HTML
<div class="wrapper">
<div class="page-container">
<button class="show-side">Show Side Container</button>
</div>
<div class="side-container">
<button class="close-side">Close Side Container</button>
<div class="large-content"></div>
</div>
</div>
CSS
html,
body,
*,
*:after,
*:before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
height: 100%;
}
.wrapper {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
}
.page-container, .side-container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border: 5px solid;
overflow-y: auto;
overflow-x: hidden;
-webkit-transition: -webkit-transform 0.2s cubic-bezier(0.68, 0, 0, 1);
transition: -webkit-transform 0.2s cubic-bezier(0.68, 0, 0, 1), transform 0.2s cubic-bezier(0.68, 0, 0, 1);
}
.page-container {
-webkit-transform: translate(0,0);
transform: translate(0,0);
}
.page-container-hidden {
-webkit-transform: translate(-100%,0);
transform: translate(-100%,0);
}
.side-container {
-webkit-transform: translate(100%,0);
transform: translate(100%,0);
}
.side-container-visible {
-webkit-transform: translate(0,0);
transform: translate(0,0);
}
.large-content {
height: 2000px;
}
JS
$('.show-side').click(function(){
$('.page-container').addClass('page-container-hidden');
$('.side-container').addClass('side-container-visible');
});
$('.close-side').click(function(){
$('.page-container').removeClass('page-container-hidden');
$('.side-container').removeClass('side-container-visible');
});
It gets more interesting
If you make the original "page-container" element have enough content that to force it to have overflow, then the "side-container" element no longer displays the aforementioned bug!
http://codepen.io/msorrentino/full/WvzgQZ/
Any thoughts on what is happening here are welcome, and any possible fixes would be very welcome.
Came across this question when I encountered a very similar problem with an off-screen menu that moves on-screen when toggled.
Here's the relevant HTML and CSS, simplified:
<div class="menu">
<!-- long list of menu items here -->
</div>
.menu {
position: fixed;
top: 0;
bottom: 0;
left: 0;
transform: translateX(-100%);
transition: transform ease 125ms;
}
.menu--active {
transform: translateX(0);
}
.menu--active is toggled with a button.
Though you're looking for a non-JS solution, I thought I'd post the cleanest workaround I've found in case people end up here with the same problem.
The workaround is to simply force a focus state on the div after the transition has completed. To do this, you first have to give the div a tabindex so that it can be focused.
<div class="menu" tabindex="-1">
<!-- long list of menu items here -->
</div>
(A value of -1 should keep the div out of the normal tab order.)
Then, using a bit of delayed jQuery, focus on the div. This should be invoked along with whatever logic you use to "activate" your div.
setTimeout( function() {
$('.menu').focus();
},150);
The time here is 150 milliseconds, which is just after the transition should have completed. A value equal to that of the transition duration would probably work too, but I set it longer just to be safe.
A more complete example might be:
$('.menuButton').on('click', function() {
$('.menu').addClass('menu--active');
setTimeout( function() {
$('.menu').focus();
},150);
});
Finally, you probably won't want the focus outline on the focused div, so you might choose to remove it with an outline: none in the style rule for your div. In my project, but not in the original example in the question, this actually broke focus on the div, and it went back to being un-scrollable. So I did this instead:
.menu:focus {
outline-color: transparent;
}
I forked the original example and included this solution here: http://codepen.io/johntobinme/full/MaPMgY
You have overflow-y set to auto, meaning it will create a scroll bar for off screen content. Since .large-content has such a large height, it goes off screen. Simply set overflow-y to none and this will no longer occur. Not a bug, just user error.
I've run into a rather strange problem. I have a div that is rotatable via CSS3. The div has a front div child and back div child, with the back div having -webkit-transform: rotateY( 180deg ) set.
The problem that once the parent element is rotated to display the back side of the div, it will only detect clicks of child elements on exactly one side of the div, specifically the second half of the div or right side. The front side div detects clicks on the entire face of element. Also, the z-indexes are fine. I assume that the issue may be due to the rotation and the browser displaying one half of the side "closer"?
The code that this is breaking is extremely complex, so I created a test file to demonstrate the problem below. I'm using a jQuery plugin I wrote for the 3D transformations, which can be found here https://github.com/pwhisenhunt/jquery.transform/blob/master/jquery.transform.js.
Edit: After experimentation, the clicking of the button element is only registering from 100-200px and not from 0-100px. In other words, it is in fact only registering on the second half of the div.
Any help is very much appreciated!
<html>
<head>
<style>
.element{
width:200;
height:200;
-webkit-perspective: 800;
-webkit-transform-style: preserve-3d;
}
.element figure {
display: block;
height: 100%;
width: 100%;
position: absolute;
-webkit-backface-visibility: hidden;
border:1px solid yellow;
}
.element .front {
-webkit-border-radius:8px;
padding: 0px;
margin: 0px;
background-color:yellow;
z-index: 9870;
}
.element .back {
-webkit-border-radius:8px;
padding: 0px;
margin: 0;
-webkit-transform: rotateY( 180deg );
z-index: 0;
border: 1px solid red;
background-color:green;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script src="https://raw.github.com/pwhisenhunt/jquery.transform/master/jquery.transform.js"></script>
<script>
$(function(){
var temp = false;
$(".element").click(function(){
if(temp == false){
$(this).transform("setAnimationDuration", 1).transform("rotateY", 180);
$(this).unbind("mouseenter mouseleave");
button = $(document.createElement('div')).attr("id", "button").css({ width: 200, height: 50, backgroundColor:"blue" });
button.click(function(){
console.log("Clicking");
});
temp = true;
$(this).append(button);
}
})
})
</script>
</head>
<body>
<div class="element">
<figure class="front"></front>
<figure class="back"></front>
</div>
</body>
</html>
A JSFiddle Example of the Problem - Can be found HERE!
I know this reply is a bit too late for most of us here, but I ran into this problem earlier today, and none of the replies helped me solve it.
Solution by #kristiankeane made the other half non-clickable. I was using a container for the wrapper as well. Turns out, it's an odd bug in webkit, and I was able to fix it and make 100% of the element clickable by changing transform: rotateY(180deg) to transform: rotateY(-180deg)
It's really odd, and I don't know how it worked, but it did. I hope this helps someone!
I had this exact same issue, was able to fix it by slightly changing the parent rotation when flipped - I changed
`.flip-holder.flipped {
-webkit-transform: rotateY(180deg);
-moz-transform: rotateY(180deg);
transform: rotateY(180deg);
}`
to
`$.flip-holder.flipped {
-webkit-transform: rotateY(180.5deg);
-moz-transform: rotateY(180.5deg);
transform: rotateY(180.5deg);
}`
and the entire backface (plus overflowed elements positioned absolutely) were now clickable, and the browser did not render the extra 0.5deg of rotation so text and images are clear.
Translate both front and back just a little bit and they won't overlap.
Example:
.element .front {
-webkit-transform: translateZ(1px);
}
.element .back {
-webkit-transform: rotateY(180deg) translateZ(1px);
}
it seems that you are missing a container (in much the same way I was missing it).
see the official documentation
it's not the outer element being flipped, but a wrapper inside it. that in turn causes one of two divs to be displayed (and the transition to occur)
If your flip card structure is like this:
<div class="flipcard">
<div class="flipcard-front">
</div>
<div class="flipcard-back">
</div>
</div>
then add this to your CSS:
.flipcard:hover {
pointer-events: none;
}
.flipcard-back:hover {
pointer-events: auto;
}
could It be (and I'm just speculating) that you should use a live or delegate event bind instead of the regular. I'm speculating the click event maybe 'remembers' some how the original div position without the rotating.
After all tricks as rotate to back and rotate to 180.5 and other...
problem fixed only the following way:
When the rotation ends - create new element, clone html from rotated element, and insert new element instead of old