J'ai une série de liens qui utilisent un mécanisme d'ancrage:
<div class="header">
<p class="menu"><a href="#S1">Section1</a></p>
<p class="menu"><a href="#S2">Section2</a></p>
...
</div>
<div style="width: 100%;">
<a name="S1" class="test"> </a>
<div class="curtain">
Lots of text
</div>
<a name="S2" class="test"> </a>
<div class="curtain">
lots of text
</div>
...
</div>
J'utilise les CSS suivants:
.test
{
position:relative;
margin: 0;
padding: 0;
float: left;
display: inline-block;
margin-top: -100px; /* whatever offset this needs to be */
}
Ça fonctionne bien. Mais bien sûr, on saute d’une section à l’autre quand on clique sur le lien. Je voudrais donc avoir une transition en douceur, en utilisant un rouleau de quelque sorte au début de la section sélectionnée
Je pense avoir lu sur Stackoverflow que cela n’était pas (encore) possible avec CSS3 mais je voudrais une confirmation et j'aimerais aussi savoir quelle solution pourrait être. Je suis heureux d'utiliser JS mais je ne peux pas utiliser jQuery. J'ai essayé d'utiliser une fonction sur le lien sur le lien, récupérer la "position verticale" de la div qui doit être affichée, mais j'ai échoué. J'apprends encore JS et je ne le connais pas assez bien pour proposer une solution personnelle.
Toute aide/idées serait grandement appréciée.
Bien que certaines des réponses aient été très utiles et instructives, j'ai pensé écrire la réponse que j'ai trouvée. La réponse d’Alex a été très bonne. Elle est toutefois limitée au sens où la hauteur de la div doit être codée en dur dans le CSS.
Donc, la solution que j'ai proposée utilise JS (no jQuery) et est en fait une version simplifiée (presque au minimum) de solutions permettant de résoudre des problèmes similaires que j'ai trouvés sur Statckoverflow:
HTML
<div class="header">
<p class="menu"><a href="#S1" onclick="test('S1'); return false;">S1</a></p>
<p class="menu"><a href="#S2" onclick="test('S2'); return false;">S2</a></p>
<p class="menu"><a href="#S3" onclick="test('S3'); return false;">S3</a></p>
<p class="menu"><a href="#S4" onclick="test('S4'); return false;">S3</a></p>
</div>
<div style="width: 100%;">
<div id="S1" class="curtain">
blabla
</div>
<div id="S2" class="curtain">
blabla
</div>
<div id="S3" class="curtain">
blabla
</div>
<div id="S4" class="curtain">
blabla
</div>
</div>
NOTE LE "RETOUR FAUX;" dans l'appel sur clic. Ceci est important si vous voulez éviter que votre navigateur ne saute sur le lien lui-même (et que l'effet soit géré par votre JS).
Code JS:
<script>
function scrollTo(to, duration) {
if (document.body.scrollTop == to) return;
var diff = to - document.body.scrollTop;
var scrollStep = Math.PI / (duration / 10);
var count = 0, currPos;
start = element.scrollTop;
scrollInterval = setInterval(function(){
if (document.body.scrollTop != to) {
count = count + 1;
currPos = start + diff * (0.5 - 0.5 * Math.cos(count * scrollStep));
document.body.scrollTop = currPos;
}
else { clearInterval(scrollInterval); }
},10);
}
function test(elID)
{
var dest = document.getElementById(elID);
scrollTo(dest.offsetTop, 500);
}
</script>
C'est incroyablement simple. Il trouve la position verticale de la div dans le document en utilisant son identifiant unique (dans la fonction test). Il appelle ensuite la fonction scrollTo en passant la position de départ (document.body.scrollTop) et la position de destination (dest.offsetTop). Il effectue la transition en utilisant une sorte de courbe d’ajustement.
Merci à tous pour votre aide.
Connaître un peu de code peut vous aider à éviter les bibliothèques (parfois lourdes) et à vous donner (au programmeur) plus de contrôle.
Vous pouvez trouver la réponse à votre question à la page suivante:
https://stackoverflow.com/a/17633941/2359161
Voici le JSFiddle qui a été donné:
Notez la section de défilement à la fin du CSS, plus précisément:
/*
*Styling
*/
html,body {
width: 100%;
height: 100%;
position: relative;
}
body {
overflow: hidden;
}
header {
background: #fff;
position: fixed;
left: 0; top: 0;
width:100%;
height: 3.5rem;
z-index: 10;
}
nav {
width: 100%;
padding-top: 0.5rem;
}
nav ul {
list-style: none;
width: inherit;
margin: 0;
}
ul li:nth-child( 3n + 1), #main .panel:nth-child( 3n + 1) {
background: rgb( 0, 180, 255 );
}
ul li:nth-child( 3n + 2), #main .panel:nth-child( 3n + 2) {
background: rgb( 255, 65, 180 );
}
ul li:nth-child( 3n + 3), #main .panel:nth-child( 3n + 3) {
background: rgb( 0, 255, 180 );
}
ul li {
display: inline-block;
margin: 0 8px;
margin: 0 0.5rem;
padding: 5px 8px;
padding: 0.3rem 0.5rem;
border-radius: 2px;
line-height: 1.5;
}
ul li a {
color: #fff;
text-decoration: none;
}
.panel {
width: 100%;
height: 500px;
z-index:0;
-webkit-transform: translateZ( 0 );
transform: translateZ( 0 );
-webkit-transition: -webkit-transform 0.6s ease-in-out;
transition: transform 0.6s ease-in-out;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.panel h1 {
font-family: sans-serif;
font-size: 64px;
font-size: 4rem;
color: #fff;
position:relative;
line-height: 200px;
top: 33%;
text-align: center;
margin: 0;
}
/*
*Scrolling
*/
a[ id= "servicios" ]:target ~ #main article.panel {
-webkit-transform: translateY( 0px);
transform: translateY( 0px );
}
a[ id= "galeria" ]:target ~ #main article.panel {
-webkit-transform: translateY( -500px );
transform: translateY( -500px );
}
a[ id= "contacto" ]:target ~ #main article.panel {
-webkit-transform: translateY( -1000px );
transform: translateY( -1000px );
}
<a id="servicios"></a>
<a id="galeria"></a>
<a id="contacto"></a>
<header class="nav">
<nav>
<ul>
<li><a href="#servicios"> Servicios </a> </li>
<li><a href="#galeria"> Galeria </a> </li>
<li><a href="#contacto">Contacta nos </a> </li>
</ul>
</nav>
</header>
<section id="main">
<article class="panel" id="servicios">
<h1> Nuestros Servicios</h1>
</article>
<article class="panel" id="galeria">
<h1> Mustra de nuestro trabajos</h1>
</article>
<article class="panel" id="contacto">
<h1> Pongamonos en contacto</h1>
</article>
</section>
scroll-behavior
CSS:(qui est supporté dans les navigateurs modernes mais pas Edge):
a {
display: inline-block;
padding: 5px 7%;
text-decoration: none;
}
nav, section {
display: block;
margin: 0 auto;
text-align: center;
}
nav {
width: 350px;
padding: 5px;
}
section {
width: 350px;
height: 130px;
overflow-y: scroll;
border: 1px solid black;
font-size: 0;
scroll-behavior: smooth; /* <----- THE SECRET ---- */
}
section div{
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-size: 8vw;
}
<nav>
<a href="#page-1">1</a>
<a href="#page-2">2</a>
<a href="#page-3">3</a>
</nav>
<section>
<div id="page-1">1</div>
<div id="page-2">2</div>
<div id="page-3">3</div>
</section>
Seul mozzila implémente une propriété simple en css: http://caniuse.com/#search=scroll-behavior
vous devrez au moins utiliser JS.
Personnellement, je l’utilise parce que c’est facile à utiliser (utilisez JQ mais je pense que vous pouvez l’adapter):
/*Scroll transition to anchor*/
$("a.toscroll").on('click',function(e) {
var url = e.target.href;
var hash = url.substring(url.indexOf("#")+1);
$('html, body').animate({
scrollTop: $('#'+hash).offset().top
}, 500);
return false;
});
il suffit d'ajouter la classe toscroll à votre balise
Si quelqu'un comme moi est prêt à utiliser jQuery, mais qu'il se trouve toujours à la recherche de cette question, cela peut vous aider:
https://html-online.com/articles/animated-scroll-anchorid-function-jquery/
$(document).ready(function () {
$("a.scrollLink").click(function (event) {
event.preventDefault();
$("html, body").animate({ scrollTop: $($(this).attr("href")).offset().top }, 500);
});
});
<a href="#anchor1" class="scrollLink">Scroll to anchor 1</a>
<a href="#anchor2" class="scrollLink">Scroll to anchor 2</a>
<p id="anchor1"><strong>Anchor 1</strong> - Lorem ipsum dolor sit amet, nonumes voluptatum mel ea.</p>
<p id="anchor2"><strong>Anchor 2</strong> - Ex ignota epicurei quo, his ex doctus delenit fabellas.</p>
J'ai implémenté la réponse suggéré par @ user18490 mais j'ai rencontré deux problèmes:
undefined
mentionnée par @krivarJ'ai développé le cours suivant pour contourner les problèmes mentionnés et cela fonctionne bien:
export class SScroll{
constructor(){
this.delay=501 //ms
this.duration=500 //ms
this.lastClick=0
}
lastClick
delay
duration
scrollTo=(destID)=>{
/* To prevent "bounce" */
/* https://stackoverflow.com/a/28610565/3405291 */
if(this.lastClick>=(Date.now()-this.delay)){return}
this.lastClick=Date.now()
const dest=document.getElementById(destID)
const to=dest.offsetTop
if(document.body.scrollTop==to){return}
const diff=to-document.body.scrollTop
const scrollStep=Math.PI / (this.duration/10)
let count=0
let currPos
const start=window.pageYOffset
const scrollInterval=setInterval(()=>{
if(document.body.scrollTop!=to){
count++
currPos=start+diff*(.5-.5*Math.cos(count*scrollStep))
document.body.scrollTop=currPos
}else{clearInterval(scrollInterval)}
},10)
}
}
Il y a un problème avec Firefox comme mentionné ici . Par conséquent, pour que cela fonctionne avec Firefox, j'ai implémenté le code suivant. Cela fonctionne très bien sur les navigateurs à base de chrome et aussi Firefox.
export class SScroll{
constructor(){
this.delay=501 //ms
this.duration=500 //ms
this.lastClick=0
}
lastClick
delay
duration
scrollTo=(destID)=>{
/* To prevent "bounce" */
/* https://stackoverflow.com/a/28610565/3405291 */
if(this.lastClick>=(Date.now()-this.delay)){return}
this.lastClick=Date.now()
const dest=document.getElementById(destID)
const to=dest.offsetTop
if((document.body.scrollTop || document.documentElement.scrollTop || 0)==to){return}
const diff=to-(document.body.scrollTop || document.documentElement.scrollTop || 0)
const scrollStep=Math.PI / (this.duration/10)
let count=0
let currPos
const start=window.pageYOffset
const scrollInterval=setInterval(()=>{
if((document.body.scrollTop || document.documentElement.scrollTop || 0)!=to){
count++
currPos=start+diff*(.5-.5*Math.cos(count*scrollStep))
/* https://stackoverflow.com/q/28633221/3405291 */
/* To support both Chromium-based and Firefox */
document.body.scrollTop=currPos
document.documentElement.scrollTop=currPos
}else{clearInterval(scrollInterval)}
},10)
}
}
Voici une solution purement css utilisant des unités de visualisation et des variables qui s'adapte automatiquement au périphérique (et fonctionne avec le redimensionnement de fenêtre). J'ai ajouté ce qui suit à la solution d'Alex:
html,body {
width: 100%;
height: 100%;
position: fixed;/* prevents scrolling */
--innerheight: 100vh;/* variable 100% of viewport height */
}
body {
overflow: hidden; /* prevents scrolling */
}
.panel {
width: 100%;
height: var(--innerheight); /* viewport height */
a[ id= "galeria" ]:target ~ #main article.panel {
-webkit-transform: translateY( calc(-1*var(--innerheight)) );
transform: translateY( calc(-1*var(--innerheight)) );
}
a[ id= "contacto" ]:target ~ #main article.panel {
-webkit-transform: translateY( calc(-2*var(--innerheight)) );
transform: translateY( calc(-2*var(--innerheight)) );
J'imagine qu'il serait peut-être possible de définir une sorte de transition difficile vers le style top
d'un #container
div
pour déplacer toute la page dans la direction souhaitée lorsque vous cliquez sur votre ancre. Quelque chose comme ajouter une classe qui a top:-2000px
.
JQuery, j’ai utilisé parce que je suis trop fainéant, j’utilise aussi JS en natif, mais ce n’est pas nécessaire pour ce que j’ai fait.
Ce n'est probablement pas la meilleure solution possible car le contenu du haut se déplace simplement vers le haut et vous ne pouvez pas le récupérer facilement. Vous devez absolument utiliser JQuery si vous avez vraiment besoin de cette animation par défilement.