Przewijanie do zakotwiczenia za pomocą przejścia / CSS3
Mam serię linków, które używają mechanizmu kotwicy:
<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>
Używam następującego CSS:
.test
{
position:relative;
margin: 0;
padding: 0;
float: left;
display: inline-block;
margin-top: -100px; /* whatever offset this needs to be */
}
Działa dobrze. Ale oczywiście przeskakuje z jednej sekcji do drugiej, gdy klikamy na link. Więc chciałbym mieć płynne przejście, używając jakiegoś zwoju na początek wybranego
sekcja.
Myślę, że czytałem na Stackoverflow, że to nie jest możliwe (jeszcze) z CSS3, ale chciałbym potwierdzenie i również chciałbym wiedzieć, co "może" być rozwiązanie. Cieszę się, że mogę używać JS, ale nie mogę używać jQuery. Próbowałem użyć funkcji kliknięcia na link, pobrać "pozycję pionową" div, który musi być wyświetlany, ale nie powiodło mi się. Wciąż uczę się JS i nie znam go na tyle dobrze, aby wymyślić własne rozwiązanie.
Każda pomoc / pomysły będą bardzo mile widziane.
8 answers
Odpowiedź na swoje pytanie znajdziesz na następującej stronie:
Https://stackoverflow.com/a/17633941/2359161
Oto jsfiddle, który został podany:
Zwróć uwagę na sekcję przewijania na końcu CSS, a konkretnie:
/*
*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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-10 18:38:57
Chociaż niektóre odpowiedzi były bardzo przydatne i pouczające, pomyślałem, że napiszę odpowiedź, którą wymyśliłem. Odpowiedź Alexa była bardzo dobra, jest jednak ograniczona w tym sensie, że wysokość div musi być mocno zakodowana w CSS.
Więc rozwiązanie, które wymyśliłem, używa JS (bez jQuery) i jest w rzeczywistości okrojoną wersją (prawie do minimum) over solutions do rozwiązania podobnych problemów, które znalazłem na 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>
Uwaga "RETURN FALSE;" w wywołaniu on click. jest to ważne, jeśli chcesz uniknąć przeskakiwania przeglądarki do samego linku (i pozwolić, aby efekt był zarządzany przez twój JS).
Kod 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>
To niezwykle proste. Znajduje pionową pozycję div w dokumencie za pomocą jego unikalnego identyfikatora (w teście funkcji). Następnie wywołuje funkcję scrollTo przekazującą pozycję początkową (document.ciało.scrollTop) i pozycji docelowej (dest.offsetTop). Wykonuje Przejście za pomocą krzywej łatwości wejścia.
Dziękuję wszystkim za pomoc.
Znajomość trochę kodowania może pomóc ci uniknąć (czasami ciężkich) bibliotek i dać ci (programiście) większą kontrolę.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-22 03:57:39
Za pomocą scroll-behavior
właściwość CSS:
(która jest obsługiwana w nowoczesnych przeglądarkach, ale nie 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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-15 08:52:21
Tylko mozzila implementuje prostą właściwość w css : http://caniuse.com/#search=scroll-behavior
Będziesz musiał użyć JS przynajmniej.
Używam tego, ponieważ jest łatwy w użyciu (użyj JQ, ale możesz go chyba dostosować):
/*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;
});
Po prostu dodaj klasę toscroll do twojego tagu a
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-27 09:08:25
Jeśli ktoś jest tak jak ja chętny do korzystania z jQuery, ale i tak znalazł się na tym pytaniu to może wam to pomóc:
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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-30 09:40:23
Chyba da się ustawić jakieś hardcore ' owe przejście na styl top
#container
div
aby przesunąć całą stronę w żądanym kierunku po kliknięciu kotwicy. Coś jak dodanie klasy, która ma top:-2000px
.
Użyłem JQuery, ponieważ też jestem leniwy, używam natywnego JS, ale nie jest to konieczne do tego, co zrobiłem.
Prawdopodobnie nie jest to najlepsze możliwe rozwiązanie, ponieważ górna zawartość po prostu przesuwa się w kierunku góry i nie można jej łatwo odzyskać, możesz zdecydowanie powinieneś użyć JQuery, jeśli naprawdę potrzebujesz animacji przewijania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-29 17:00:20
Oto czyste rozwiązanie css wykorzystujące jednostki viewport i zmienne, które automatycznie skalują się do urządzenia (i działają przy zmianie rozmiaru okna). Dodałem do rozwiązania Alexa:
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)) );
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-25 15:59:32
Zaimplementowałem odpowiedź zasugerowaną przez @user18490, ale napotkałem dwa problemy:
- pierwsze odbijanie gdy użytkownik klika kilka kart/linków wielokrotnie w krótkim odstępie czasu
- Po Drugie,
undefined
Błąd wymieniony przez @ krivar
Opracowałem następującą klasę, aby ominąć wspomniane problemy i działa dobrze: {]}
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)
}
}
UPDATE
Jest problem z Firefoksem, jak wspomniano tutaj . Dlatego, aby działał na Firefoksie, zaimplementowałem następujący kod. Działa dobrze na przeglądarkach opartych na Chromium, a także Firefoksie.
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)
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-28 06:07:19