I'm trying to add a transition between pages in a SvelteKit application. When navigating, the current page should fade out, and the new page should then fade in in its place. To accomplish this, in +layout.svelte, I wrapped the <slot> in a div with the in and out transitions set. I wrapped this all in {#key $page.url.pathname} so that the animations are triggered when navigating from page to page. However, my current code produces this effect:
When navigating, the content of the page updates before fading out. In other words, the destination page immediately appears, then fades out, then fades back in. At the same time, though, content in +layout.svelte (.title, at the top of the page) behaves correctly; just the content within the <slot> is bugged.
Here is the code:
+layout.svelte
<script lang="ts">
import '$lib/style.css';
import { page } from '$app/stores';
import { fade } from 'svelte/transition';
</script>
<div class="page">
<div class="bar">
Sidebar
Page 1
Page 2
</div>
<div class="content-wrapper">
{#key $page.url.pathname}
<div class="content" in:fade={{ delay: 1000, duration: 1000 }} out:fade={{ duration: 1000 }}>
<div class="title">
{$page.url.pathname}
</div>
<slot />
</div>
{/key}
</div>
</div>
<style global>
.page {
display: flex;
flex-direction: row;
box-sizing: border-box;
width: 100vw;
min-height: 100vh;
}
.bar {
display: flex;
flex-direction: column;
width: 300px;
color: white;
background: black;
}
a {
color: white;
}
.content-wrapper {
flex-grow: 1;
width: 100%;
min-height: 100vh;
}
.content {
width: 100%;
height: 100%;
}
.title {
font-size: 2em;
}
</style>
+page.svelte
<div class="page">
<div class="title">Page 1</div>
</div>
<style>
.page {
width: 100%;
height: 100%;
background: blue;
}
</style>
page2/+page.svelte
<div class="page">
<div class="title">Page 2</div>
</div>
<style>
.page {
width: 100%;
height: 100%;
background: red;
}
</style>
Is there a way to get the <slot> content to wait for the out animation to finish before updating?
Its an issue with the lifecycle of the transitions for in and out.
I usually use in:fade ONLY on elements and it looks okay. It seems using both means that while one element is going out, another is coming in at the same time in which looks funny.
Perhaps you could find out more about delay in transitions and let us know..
Happy coding☺️
Related
I'd like to have a header and then three images side-by-side.
When in small screens, the images should occupy all the width and be placed vertically one after another.
For each image, when the mouse is over it, some text should be overlayed.
For mobile and touch screens, I don't know how that text could be shown, but would like to have it shown in some way.
Each of the images should point to another html page (not shown in my example.
What I managed to do until now is:
<!DOCTYPE html>
<html>
<head>
<style>
html {
font-family: helvetica, arial, sans-serif;
}
.cabecalho {
width:70%;
height:200px;
text-align:center;
margin:70px;
margin-top:10px;
}
.cabecalho p{
line-height: 10px; /* within paragraph */
margin-bottom: 4px; /* between paragraphs */
}
.corpo {
width:60%;
height:500px;
}
* {
box-sizing: border-box;
}
.img__description_layer {
position: relative;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(204, 204, 204, 0.6);
color: #111;
visibility: hidden;
opacity: 0;
display: flex;
align-items: center;
justify-content: center;
pad: 8px;
height: 300px;
width: 200px;
/* transition effect. not necessary */
transition: opacity .2s, visibility .2s;
}
.img__description {
transition: .2s;
transform: translateY(1em);
}
.img__wrap:hover .img__description {
transform: translateY(0);
}
.img__wrap:hover .img__description_layer {
visibility: visible;
opacity: 1;
}
.column {
float: left;
width: 33.33%;
padding: 5px;
}
/* Clearfix (clear floats) */
.row::after {
content: "";
clear: both;
display: table;
}
/* Responsive layout - makes the three columns stack on top of each other instead of next to each other */
#media screen and (max-width: 500px) {
.column {
width: 100%;
}
}
</style>
</style>
</head>
<body>
<div class="cabecalho">
<header>
</header>
</div>
<main>
<div class="row">
<div class="column">
<div class="img__wrap">
<img class="img__img" alt="alttext" align="middle" src="http://placehold.it/257x200.jpg" width="300" height="200" style="width:100%">
<div class="img__description_layer">
<p class="img__description">Some paragraph</p>
</div>
</div>
</div>
<div class="column">
<div class="img__wrap">
<img class="img__img" alt="alttext" align="middle" src="http://placehold.it/257x200.jpg" width="300" height="200" style="width=100%">
<div class="img__description_layer">
<p class="img__description">Some paragraph</p>
</div>
</div>
</div>
<div class="column">
<div class="img__wrap">
<img class="img__img" alt="alttext" align="middle" src="http://placehold.it/257x200.jpg" width="300" height="200" style="width=100%">
<div class="img__description_layer">
<p class="img__description">Some paragraph</p>
</div>
</div>
</div>
</div>
</main>
</body>
</html>
I'd appreciate some help on this.
I'm trying to use bootstrap grid to format my webpage layout. There are two elements on my page, an image and a subtitle for the image. I would like that both elements occupy the whole screen of a smartphone, just under the navbar. Could anyone help me? I'm also tryint to make it looks nice on pc and other plataforms.
I have done some progress using media screen, but its still clunky.
Thats my .index html:
<div class="row">
<div class="combocontainer col-lg-12">
<div class="combocontainer">
<div class="top-container">
<img class="avatar" src="Images/minimalist.jpg" alt="avatar" />
</div>
<div class="signature">
<h1>My Name</h1>
</div>
</div>
</div>
</div>
Thats my css:
.avatar {
display: block;
margin-top: 220px;
margin-left: auto;
margin-right: auto;
height: 100%;
width: 100%;
}
.combocontainer{
height: 100vh;
}
#media screen and (min-width: 1000px) {
.combocontainer {
display: block;
margin-top: 6rem;
margin-left: auto;
margin-right: auto;
height: 20%;
width: 20%;
}
}
/* No implementation yet */
.signature {
text-align: center;
height: 20%;
width: 20%;
font-family: "romatehood-p73ed-webfont";
}
I'm trying to scroll content vertically in a div. However, I would like it to loop, so that when the last item in the div reaches the top of the container, the first items follow it, and if the first item is already at the top of my container, I don't want the previous button to work, but I'm not sure how to do either of these two things. Any help would be appreciated.
JSFIDDLE
HTML
<div class="container">
<div class="block block-1">1</div>
<div class="block block-2">2</div>
<div class="block block-3">3</div>
<div class="block block-4">4</div>
<div class="block block-5">5</div>
<div class="block block-6">6</div>
</div>
<button id="prev">Previous</button>
<button id="next">Next</button>
jQuery
$( "#prev" ).click(function()
{
$( ".block" ).animate({ "top": "+=50px" }, "slow" );
});
$( "#next" ).click(function()
{
$( ".block" ).animate({ "top": "-=50px" }, "slow" );
});
CSS
.container
{
position: relative;
background-color: #f5f5f5;
width: 590px;
height: 330px;
overflow: hidden;
font-family: arial, sans;
font-weight: bold;
text-align: center;
margin-bottom: 20px;
}
.block
{
position: absolute;
width: 90px;
height: 90px;
color: #fff;
}
.block-1
{
background-color: #900;
}
.block-2
{
top: 100px;
background-color: #090;
}
.block-3
{
top: 200px;
background-color: #009;
}
.block-4
{
top: 300px;
background-color: #990;
}
.block-5
{
top: 400px;
background-color: #909;
}
.block-6
{
top: 500px;
background-color: #099;
}
If you want it to loop, you can do a test where every time a div's vertical position goes out of bounds, it gets moved to the bottom of the pile, and reverse this when scrolling up. Essentially you just cut and paste the elements in the right order using $.remove(), $.append(), $.clone().
html code:
<div class="container">
<a class="ank">
<img src="http://www.w3schools.com/images/w3schoolslogoNEW310113.gif" />
</a>
</div>
css code:
.ank
{
display: block;
width: 500px;
height: 500px;
line-height: 100%;
}
img
{
vertical-align: middle;
}
.container
{
display:block;
width: 500px;
height: 500px;
border: 1px solid black;
font-size: 500px;
}
jsfiddle: http://jsfiddle.net/mfBZZ/5/
if i change the jsfiddle, so that anks line-height is 500px, and remove the font-size from container, it works.
but when i add the font-size to container of 500px, and then make the line-height in ank, 100% of that font-size, it doesn't work. it brings the image alittle lower than where it should be.
working jsfiddle: http://jsfiddle.net/eujFY/1/
UPDATE:
this solution works for me:
http://jsfiddle.net/eujFY/2/ <---- updated.
I've seen you found a solution, however it implies setting the height manually on both elements and it requires the usage of unnecessary tags.
So I suggest you to check the "display:table" (container) and "display:table-cell" (inner element) rules: http://jsfiddle.net/RxGS5/
HTML
<div class="container">
<a class="ank">
<img src="http://www.w3schools.com/images/w3schoolslogoNEW310113.gif" />
</a>
</div>
CSS
.container
{
display:table;
width: 500px;
height: 500px;
border: 1px solid black;
}
.ank
{
display: table-cell;
vertical-align: middle;
}
I have an awkward visual glitch. I want a nice transition when changing pages on an app.
Unfortunately, the first time I change to another page, instead of sliding the current page out and the new page in, the current page is immediately replaced by the new page and then slides out. When the first page is out of view, the new page is shown. However, the second time around, it works like a charm!
This is running on iphone with jQuery Mobile + PhoneGap
I made a video to help clarify the issue: http://www.youtube.com/watch?v=Ybvzh_wTnSE
<body style="background-color: #000;">
<div id="container" style="display:none;">
<div id="side-menu" style="display:none;">
<div id="header_top"></div>
<div id="header_dives" class="selected"></div>
<div id="header_spacer1"></div>
<div id="header_explore"></div>
<div id="header_spacer2"></div>
<div id="header_search"></div>
<div id="header_spacer3"></div>
<div id="header_settings"></div>
<div id="header_bottom"></div>
</div>
<div id="slide_mask">
<!-- START of LOGIN page -->
<div data-role="page" id="login">
<div id="home_frame">
<div id="home_logo"></div>
<div id="home_fblogin" onclick="login()"></div>
<div class="home_login">
<p>Email: <input type="text" name="user[email]" size="30"/></p>
<p>Password: <input type="password" name="user[password]" size="30"/></p>
<button onclick="show_page_home();">LOGIN</button>
</div>
</div>
</div>
<!-- END of LOGIN page -->
<!-- START of LOGIN page -->
<div data-role="page" id="dives" class="right_pane">
<p>My dives !</p>
</div><!-- /content -->
<div data-role="page" id="explore" class="hidden right_pane">
<p>My explore !</p>
</div><!-- /content -->
<div data-role="page" id="search" class="hidden right_pane">
<p>My search !</p>
</div><!-- /content -->
<div data-role="page" id="settings" class="hidden right_pane">
<p>My settings !</p>
<button onclick="logout_db();">logout</button>
</div><!-- /content -->
<!-- END of LOGIN page -->
</div>
</div>
<div id="log"></div>
<div id="data"></div>
</body>
And the relevant CSS:
body {margin: 0; font: 18px Helvetica; text-align: center; background-color: #000; background: url(../img/bg_big.png) repeat;
-webkit-user-select: none; /* prevent copy paste for all elements */
}
#container { width:320px; height:460px; overflow: hidden;}
input{ -webkit-user-select: text; /* enable copy paste for elements with this class */}
a {-webkit-user-select: none; /* prevent copy paste for all elements */}
span {-webkit-user-select: none; /* prevent copy paste for all elements */}
#side-menu {z-index: 1000 !important; position: fixed; height: 460px; width: 56.5px; background: url(../img/bg_big.png) no-repeat; display: inline-block;
overflow: hidden; top: 0px; left: 0px; }
#header_top {background: url(../img/header/header_top.png) no-repeat; background-size: 56.5px 48.96px; width: 56.5px; height: 48.96px; display: block;}
#header_dives {background: url(../img/header/dives.png) no-repeat; background-size: 56.5px 51.75px; width: 56.5px; height: 51.75px; display: block;}
#header_dives.selected{background: url(../img/header/dives_selected.png) no-repeat;}
#header_spacer1{background: url(../img/header/header_space1.png) no-repeat; background-size: 56.5px 13.9px; width: 56.5px; height: 13.9px; display: block;}
#header_explore{background: url(../img/header/explore.png) no-repeat; background-size: 56.5px 51.75px; width: 56.5px; height: 51.75px; display: block;}
#header_explore.selected{background: url(../img/header/explore_selected.png) no-repeat;}
#header_spacer2{background: url(../img/header/header_space2.png) no-repeat; background-size: 56.5px 15.33px; width: 56.5px; height: 15.33px; display: block;}
#header_search{background: url(../img/header/search.png) no-repeat; background-size: 56.5px 51.75px; width: 56.5px; height: 51.75px; display: block;}
#header_search.selected{background: url(../img/header/search_selected.png) no-repeat;}
#header_spacer3{background: url(../img/header/header_space3.png) no-repeat; background-size: 56.5px 17.73px; width: 56.5px; height: 17.73px; display: block;}
#header_settings{background: url(../img/header/settings.png) no-repeat; background-size: 56.5px 51.75px; width: 56.5px; height: 51.75px; display: block;}
#header_settings.selected{background: url(../img/header/settings_selected.png) no-repeat;}
#header_bottom{background: url(../img/header/header_bottom.png) no-repeat; background-size: 56.5px 160px; width: 56.5px; height: 160px; display: block;}
.hidden {display: none;}
.right_pane{width: 263.5px !important; background: url(../img/right_bg.png) no-repeat; background-size:263.5px 460px; width: 263.5px; height: 460px; left: 56.5px !important;}
#slide_mask{ display: inline-block; overflow: hidden; padding-left: 56.5px; width: 263.5px; height: 460px; top: 0;}
and the bit of JS:
///////////////////////////////////
//MENU MECHANICS
///////////////////////////////////
function showdives(){
$("#side-menu .selected").removeClass("selected");
$("#header_dives").addClass("selected");
}
function showexplore(){
$("#side-menu .selected").removeClass("selected");
$("#header_explore").addClass("selected");
}
function showsearch(){
$("#side-menu .selected").removeClass("selected");
$("#header_search").addClass("selected");
}
function showsettings(){
$("#side-menu .selected").removeClass("selected");
$("#header_settings").addClass("selected");
}
The onclick methods only add/remove the "selected" class to/from the menu items.
I believe people refer to this as "flickering", so you'll have better results when you search for that. After looking around, it looks like your problem is common on android and can be solved by adding the following CSS:
.ui-page {
-webkit-backface-visibility: hidden;
}
Here are a few references:
http://blogs.bytecode.com.au/glen/2011/07/14/eliminating-annoying-flicker-transitions-with.html
Flickering when navigating between pages
https://forum.jquery.com/topic/performance-of-jquery-mobile-on-android-2-2-and-2-3-flickering
I and my friends are using JQuery 1.2.
The way to solve this issue was to put data-transition="none". Maybe this cannot appear mobile
style that much, but works and delete the flickering problem.
Hope this help.
I had the same problem, but even worse, when wrapping a Jquery mobile app in Phonegap. Not only were the page transitions flickering, but the UI was completely broken. I used Jquery 1.8 and Jquery mobile 1.2 in this app.
I have tried most of the solutions suggested here on SO, but nothing worked. Then I found this solution by Piotr Walczyszyn, and everything worked like a dream! Highly recommended for anyone using Jquery mobile and Phonegap together.