HI I am playing with the CSS transform effect I am trying to create 2 divs that open showing the site. I have this working but when the doors have finished opening they reappear and hide the content, that I am looking to show!!!!!!
How do I keep the doors open when the effect is finished, thanks for any help!!
here is a basic fiddle showing the issue, http://jsfiddle.net/BaHzN/
<div id="content">
<div id="leftDoor">LEFTDOOR</div>
<div id="rightDoor">RIGHTDOOR</div>
</div>
#leftDoor{
background-color:red;
left:0px;
-webkit-animation: leftDoorOpen 4s ease 4s;
}
#rightDoor{
right:0px;
background-color:red;
-webkit-animation: rightDoorOpen 4s ease 4s;
}
#-webkit-keyframes leftDoorOpen {
from {
-webkit-transform: perspective(300) rotateY(0deg);
-webkit-transform-origin: 0% 0%;
}
to {
-webkit-transform: perspective(300) rotateY(90deg);
-webkit-transform-origin: 0% 0%;
}
}
#-webkit-keyframes rightDoorOpen {
from {
-webkit-transform: perspective(300) rotateY(0deg);
-webkit-transform-origin: 0% 0%;
}
to {
-webkit-transform: perspective(300) rotateY(-90deg);
-webkit-transform-origin: 100% 0%;
}
}
You can use -webkit-animation-fill-mode: forwards;
Mozilla Docs
JSFiddle
Related
Hi I am a mobile app developer and not much familiar with web development, I was finding any approach to implement Progress Indicator before loading the flutter web app like Gmail loading screen. Flutter web is cool but it takes few moments before loading the app. Can we add any indicator for this loading duration? Any code implemented in flutter would be the part of flutter app and it won't work, There should be another approach to achieve this.
With the help of #Abhilash, I was able to accomplish this. I got loader code from w3schools.
My project/web/index.html is like this.
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<script defer src="index.dart.js" type="application/javascript"></script>
<style>
.loading {
display: flex;
justify-content: center;
align-items: center;
margin: 0;
position: absolute;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.loader {
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid blue;
border-right: 16px solid green;
border-bottom: 16px solid red;
border-left: 16px solid pink;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
#-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
#keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div class="loading">
<div class="loader"></div>
</div>
<script src="main.dart.js" type="application/javascript"></script>
</body>
</html>
In your question you mentioned
Any code implemented in flutter would be the part of flutter app and it won't work,...
I assume you tried to add the splash screen approach for android or IOS. Since flutter-web is simply an index.html and a couple of js files(for eg., main.dart.js), you should perhaps try the CSS loading animation trick. Since you didn't share any code I am not writing any code but the following would be my approach as explained by this red stapler video. He/she kindly provided a lot of CSS based animations here along with the codepen implementations for that.
So following would be my steps in the flutter_web_project\web\index.html file.
Add a span element in the body of index.html to show the css animation itself.
Create a div wrapper to position the span animation in your index.html.
Then listen to the onLoad event of the window and remove the div element from your page or fade it out as described in the video.
In addition to answer of #Shahzad Akram you should remove the loading div because in Safari browser it may cause of flickering. So in the first screen you need to implement the folowing code (for example, in initState method):
import 'package:universal_html/html.dart'
...
#override
void initState() {
super.initState()
// Remove `loading` div
final loader = document.getElementsByClassName('loading');
if(loader.isNotEmpty) {
loader.first.remove();
}
}
P.S. For nice loaders you can visit loading.io.
Adam's answer will remove loader before flutter is actually loaded.
I found this script to be the most complete answer:
<html>
<head>
<style>
.loading {
display: flex;
flex-flow: column;
justify-content: center;
align-items: center;
margin: 0;
position: absolute;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.loader {
border: 8px solid #f3f3f3;
border-radius: 50%;
border-top: 8px solid #00AD87;
border-right: 8px solid #C30E48;
border-bottom: 8px solid #00AD87;
border-left: 8px solid #C30E48;
width: 60px !important;
height: 60px !important;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
#-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
#keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<!-- First time loading -->
<div class="loading">
<div class="loader"></div>
</div>
<!-- Ensure first time loading progress is gone after app loads -->
<script>
window.addEventListener("flutter-first-frame", function() {
var element = document.getElementsByClassName("loading");
element[0].parentNode.removeChild(element[0]);
});
</script>
<script defer src="main.dart.js" type="application/javascript"</script>
</body>
</html>
If you want to remove loading div with just JS use this code
<script>
window.onload = (event) => {
console.log('page is fully loaded');
var element = document.getElementById("loader");
element.parentNode.removeChild(element);
};
</script>
Notice that it assumes that loader is a <div id="loader"></div> tag
In addition to answers from #Shahzad and #BambinoUA, I also needed to add defer keyword for main.dart.js script tag as well.
<script defer src="main.dart.js" type="application/javascript"></script>
Below is my scenario where this was needed:
app was hosted on Gitlab pages
browser was Chrome (with a slow internet)
In this case, only blank screen was visible until the whole script is downloaded. Then the animation was visible only for 0.5 second and flutter widgets loaded immediately after that. Thus failing the purpose of having loading animation. This doesn't happen in local testing.
I also tried putting the animation div before all scripts, but it didn't help.
I think the accepted answer is partially right as it's presented a loading indicator rather than a progress indicator. From flutter doc you can have a rough estimation of the flutter's actual loading progress. I've compiled an example using this indicator and it's showcased here.
Add this style
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
width: 100%;
}
.progress-bar__container {
width: 80%;
height: 2rem;
border-radius: 2rem;
position: relative;
overflow: hidden;
transition: all 0.5s;
will-change: transform;
box-shadow: 0 0 5px #e76f51;
}
.progress-bar {
position: absolute;
height: 100%;
width: 100%;
content: "";
background-color: #e76f51;
top:0;
bottom: 0;
left: -100%;
border-radius: inherit;
display: flex;
justify-content: center;
align-items:center;
color: white;
font-family: sans-serif;
}
.progress-bar__text {
display: none;
}
and append this code on index.html of your flutter app.
function updateProgress(num) {
const progressBarContainer = document.querySelector('.progress-bar__container');
const progressBar = document.querySelector('.progress-bar');
const progressBarText = document.querySelector('.progress-bar__text');
let time = 0;
let endState = 100;
gsap.to(progressBar, {
x: num + "%",
duration: 2,
});
}
window.addEventListener('load', function(ev) {
var loading = document.querySelector('#loading');
loading.textContent = "Loading entrypoint...";
updateProgress(15);
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
},
onEntrypointLoaded: async function(engineInitializer) {
loading.textContent = "Initializing engine...";
updateProgress(50);
let appRunner = await engineInitializer.initializeEngine();
updateProgress(80);
loading.textContent = "Running app...";
await appRunner.runApp();
updateProgress(100);
}
});
});
During startup of a flutter web app, we have the 2 phases: the first phase is when the index.html page has already loaded but the actually flutter app is loading. Then when the flutter app is loaded, we still might need to do some preparation within the flutter app. I like both phases to show an indication of loading and I want this to be the same. So... what I did:
First my index.html displays a gif which shows a circular progress indicator similar to the one I have in flutter (see 2) loading.gif
I do this similar to what this person describes: https://retroportalstudio.medium.com/indicate-website-loading-for-flutter-web-apps-7dc5e2c59e24
Then in my flutter app, I show this indicator:
return Container(
decoration: BoxDecoration(color: Colors.white),
child: Center(child: CircularProgressIndicator())
);
This indicator is pretty much the same as the gif. I created this gif with a combination of https://gifcap.dev/ and gimp to crop it.
The result is a fairly smooth loading circular progress indicator almost instant upon opening my website all the way up to when my flutterweb app opens.
Mostly I'm copying the demo code from the PureCSS "docs" for implementing their dropdown menu.
I have created a CodePen, and will share code here as well.
The problem is that in the vertical version, the submenu items are not being revealed on hover or on click.
I am presuming this is by design and am not sure if it is expected that additional JavaScript (example) should be composed to enable reveal on click for touch devices and the like.
What I have is:
HTML:
<h1>PureCSS.io Responsive Nav Test</h1>
<link rel="stylesheet" href="https://unpkg.com/purecss#1.0.0/build/grids-responsive-min.css">
<link rel="stylesheet" href="https://unpkg.com/purecss#1.0.0/build/pure-min.css" integrity="sha384-nn4HPE8lTHyVtfCBi5yW9d20FjT8BJwUXyWZT9InLYax14RDjBj46LmSztkmNP9w" crossorigin="anonymous">
<s class="bar"></s><s class="bar"></s><s class="bar"></s>
<nav class="custom-wrapper pure-menu custom-restricted-width pure-u-1" id="menu">
<div class="pure-menu pure-menu-horizontal custom-can-transform">
<ul id="menu-header-nav-menu" class="pure-menu-list">
<li class="pure-menu-item">
<a class="pure-menu-link" class='pure-menu-link' href="#">One</a>
</li>
<li class="pure-menu-item">
<a class="pure-menu-link" class='pure-menu-link' href="#">Two</a>
</li>
<li class="pure-menu-item">
<a class="pure-menu-link" class='pure-menu-link' href="#">Three</a>
</li>
<li class="pure-menu-item pure-menu-has-children pure-menu-allow-hover">
<a class="pure-menu-link" class='pure-menu-link' href="#">Parent</a>
<ul class="pure-menu-children">
<li class="pure-menu-item">
<a class="pure-menu-link" class='pure-menu-link' href="#">Child One</a>
</li>
<li class="pure-menu-item">
<a class="pure-menu-link" class='pure-menu-link' href="#">Child Two</a>
</li>
</ul>
</li>
</ul>
</div>
</nav>
CSS:
.site-header {
position: relative;
}
.custom-wrapper {
margin-bottom: 1em;
-webkit-font-smoothing: antialiased;
height: 2.1em;
overflow: hidden;
-webkit-transition: height 0.5s;
-moz-transition: height 0.5s;
-ms-transition: height 0.5s;
transition: height 0.5s;
}
.custom-wrapper.open {
height: 14em;
}
.custom-wrapper {
height: 0;
}
.custom-toggle {
width: 34px;
height: 34px;
position: absolute;
top: 0;
right: 0;
display: none;
}
.custom-toggle {
display: block;
}
.custom-toggle .bar {
background-color: #777;
display: block;
width: 20px;
height: 2px;
border-radius: 100px;
position: absolute;
top: 18px;
right: 7px;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
-ms-transition: all 0.5s;
transition: all 0.5s;
}
.custom-toggle .bar:first-child {
-webkit-transform: translateY(-6px);
-moz-transform: translateY(-6px);
-ms-transform: translateY(-6px);
transform: translateY(-6px);
}
.custom-toggle .bar:last-child {
-webkit-transform: translateY(+6px);
-moz-transform: translateY(+6px);
-ms-transform: translateY(+6px);
transform: translateY(+6px);
}
.custom-toggle.x .bar:last-child {
display: none;
}
.custom-toggle.x .bar {
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.custom-toggle.x .bar:first-child {
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
}
#media (min-width: 47.999em) {
.custom-toggle {
display: none;
}
.custom-wrapper {
height: 3.2em;
overflow: visible;
}
.pure-menu-children .pure-menu-item {
background-color: #999;
}
}
Javascript:
(function (window, document) {
var menu = document.getElementById('menu'),
WINDOW_CHANGE_EVENT = ('onorientationchange' in window) ? 'orientationchange':'resize';
function toggleHorizontal() {
[].forEach.call(
document.getElementById('menu').querySelectorAll('.custom-can-transform'),
function(el){
el.classList.toggle('pure-menu-horizontal');
}
);
};
function toggleMenu() {
// set timeout so that the panel has a chance to roll up
// before the menu switches states
if (menu.classList.contains('open')) {
setTimeout(toggleHorizontal, 500);
}
else {
toggleHorizontal();
}
menu.classList.toggle('open');
document.getElementById('toggle').classList.toggle('x');
};
function closeMenu() {
if (menu.classList.contains('open')) {
toggleMenu();
}
}
document.getElementById('toggle').addEventListener('click', function (e) {
toggleMenu();
e.preventDefault();
});
window.addEventListener(WINDOW_CHANGE_EVENT, closeMenu);
})(this, this.document);
Am I correctly presuming that I need to handle the mobile subnav with additional script?
What was happening is that the "children" were off-page.
I'm not sure why it was required to modify the basic yui-pure-css mark-up, but to make this work in this case, I modified the following two items for the small screen sizes:
.pure-menu-has-children {
position: relative;
}
.pure-menu-children {
left: 3em;
top: 2em;
}
The .pure-menu-children ul has position: absolute, but I'm not sure what it's relative parent is. Maybe it's the ul. At any rate, making it's relative parent the .pure-menu-has-children li facilitates it being displayed in relation to the parent list item.
I'm using a mobile first approach, so then for the media query for the larger viewports it can be restored to the framework defaults:
.pure-menu-children {
left: 100%;
top: 0;
}
However I think I prefer it as it is on the smaller devices. Here's an updated Pen.
Not completely happy. Maybe the vertical menu doesn't need to be quite so wide. I'm also, in this case, finding the need to add to .pure-menu-link a text-align: left, because the child item still seems to be aligning based on a full-width item.
Is this possible to merge a round and a square div and show single box-shadow in css3? I know we can hide single side of border of any div. But my need is different:
Example Image
If this is possible, how can I achieve it?
you actually only need a single div, then can make use of positioning on its :before and :after pseudo elements (the below CSS is a starting point):
Demo Fiddle
CSS
div, div:before {
height:50px;
-webkit-box-shadow: 0 0 4px 0 #424242;
box-shadow: 0 0 4px 0 #424242;
position:relative;
margin-top:200px;
}
div:before {
height:100px;
margin-top:0;
width:100px;
display:block;
background:white;
position:absolute;
top:-25px;
left:100px;
content:'';
border-radius:100%;
}
div:after {
height:100%;
width:100%;
display:block;
background:white;
position:absolute;
top:-0;
left:0;
content:'';
}
Here i come with a very similar answer. with the use of z-index to make sure it works fine and that eventually, content is seen :)
<div class="shaped"> </div>
CSS
.shaped {
margin:2em 0;
box-shadow:0 0 5px;/* will be inherited by pseudo under */
height:2em;
position:relative;
background:white;/* will be inherited by pseudo on top */
}
.shaped:before, .shaped:after {
content:'';
position:absolute;
height:2em;
width:2em;
padding:1em;
background:inherit;
border-radius:100%;
margin:-1em 2em;
z-index:1;
}
.shaped:before {
box-shadow:inherit;
z-index:-1;
}
.shaped>* {/* let's see whatever comes inside */
position:relative;
z-index:2;
}
<div>
<style>
.dim {
height:100%;
width:100%;
position:fixed;
left:0;
top:0;
z-index:1 !important;
background-color:black;
filter: alpha(opacity=75); /* internet explorer */
-khtml-opacity: 0.75; /* khtml, old safari */
-moz-opacity: 0.75; /* mozilla, netscape */
opacity: 0.75; /* fx, safari, opera */
}
.wrapper {
width: 100%;
top: 0px;
left: 0px;
position: absolute;
z-index: 5;
display: block;
}
.popup { width: 400px;
height: 200px;
margin: 0 auto;
padding: 40px;
background-color: #fff;
border: 1px solid #ccc;
color: #333;
}
</style>
<div class="dim"></div>
<div class="wrapper">
<div class="popup">
Subscribe box</div>
</div>
</div>
here's the code I actually got from another post and it makes the pop up for the most part and it dims the screen but it doesn't close or have a close button so there's no way of closing it once it's opened. so add a close button?
Your going to have to do a little JavaScript to get this to work, so that the code can detect the click event on the close button. I have previously used Colorbox to handle popups as it has quite a large number of features and is well documented, although you could also create your own using CSS3 and use javascript to add or remove a class.
Something like:
<style>
#basicElement {
/* style here */
}
#basicElement.open {
/* style here */
animation: popup 25s linear;
-moz-animation: popup 25s linear;
-ms-animation: popup 25s linear;
-o-animation: popup 25s linear;
-webkit-animation: popup 25s linear;
}
#basicElement.closed {
/* style here */
animation: popup 25s linear;
-moz-animation: popup 25s linear;
-ms-animation: popup 25s linear;
-o-animation: popup 25s linear;
-webkit-animation: popup 25s linear;
animation-direction: reverse;
-moz-direction: reverse;
-ms-direction: reverse;
-o-direction: reverse;
-webkit-direction: reverse;
}
#-webkit-keyframes popup {
0% {
background-size: 100% 100%;
}
100% {
background-size: 130% 130%;
background-position: center bottom;
}
}
</style>
<script>
$('#open').click(function (){ $(this).removeClass('closed').addClass('open'); });
$('#close').click(function (){ $(this).removeClass('open').addClass('closed'); });
</script>
I am doing a iPhone app using Phonegap & also using jquery mobile. I want to set background image for data-role=page div. In this height of page is equal to screen & hence background is set to size of screen. But the page content length is much greater than screen & hence gray background is seen after image completes.
My question is whether there is a way so that we can keep the background image fixed & scroll or move only content of page & not background image.
Just to mention I have tried full size background jquery pluggin. Its working on Android but not on iOS.
Can anyone please help? Thanks in advance.
Ok, so what I did instead was to create a fixed element within the body element of the page.
So it would look like
<body>
<div id="background"></div>
...
</body>
And for the CSS I stated the following:
#background {
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
background: url(images/bg-retina.jpg) 0 0 no-repeat fixed !important;
background-size:contain;
}
And this did the trick for me. Hopefully it helps (someone out there :P)
You looking for css background-attachment property.
div[data-role="page"]{
background-attachment: fixed;
}
Update:
background-attachment:fixed is supported from iOS 5, if you using older version of iOS you may consider usage of iScroll.
you can try this:
.ui-mobile
.ui-page-active{
display:block;
overflow:visible;
overflow-x:hidden;
}
works fine for me.
You can set your background image to the jQuery page:
.ui-page { background-image:url(../ios/sample~ipad.png);
background-repeat:no-repeat; background-position:center center;
background-attachment:scroll; background-size:100% 100%; }
Try with this, this work for me.
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
background: url(../Images/loginBackground.jpg) 0 0 fixed !important;
background-size:100% 100%;
background-repeat: no-repeat;
<body>
<div id="background"></div>
...
</body>
css:
#background {
background-image: url("/images/background.png");
background-repeat: no-repeat;
background-attachment: fixed;
height: 100%;
width: 100%;
position: fixed;
background-position: 0 0;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
#media screen and (max-width: 480px) {
#background {
background-attachment: initial !important;
}
}
The problem is that iOS mobile devices have errors rendering simultaneously background-size:cover; and background-attachment:fixed; so you have to fix it by #media