In deze zelfstudie maken we een navigatiebalk die bij je blijft terwijl je scrolt - en we gooien ook een gimmick of twee in de mix om deze te poetsen.
"Iedereen houdt van linten", zegt Chris Coyier bij het bespreken van de deugden van de :voor
en :na
pseudo-elementen. Ik heb deze gestileerde linten met driehoekige randen overal op internet zien verschijnen (een prominent voorbeeld is Facebook's Introductie van de tijdlijnpagina) en hoewel ze een zekere aantrekkingskracht hebben, moet ik toegeven dat het ruimtelijke effect dat ze creëren gewoon niet goed werkt. ik zie er goed uit.
Linten zijn echter om een bepaalde reden geliefd; ze verbreken het meestal vlakke ontwerpparadigma waar we traditioneel aan gebonden zijn, en ze zijn een van de weinige visuele elementen om dit onopvallend te doen. Maar zoals het eeuwenoude gezegde luidt, moet er meer dan één manier zijn om een kat te villen - dus in deze tutorial zal ik een alternatieve visuele stijl voorstellen voor dergelijke elementen, die ik veel natuurlijker en esthetischer vind verheugend. Ik hoop dat je het leuk vindt en maak er goed gebruik van!
In deze zelfstudie gebruiken we een van HTML5's nieuwe elementen, de nav
tag, als een container voor een horizontale lijst met links. Ik zal in het kort uitleggen hoe je het er met een beetje CSS goed uit kunt laten zien.
Het belangrijkste is dat u bekend raakt met de basisprincipes van jQuery's Waypoints-plug-in, die geavanceerde functionaliteit zal bieden: als de gebruiker naar beneden scrolt, blijft de navigatiebalk aan de bovenkant van de viewport staan en verandert deze om de huidige sectie aan te geven . Als een extraatje gebruiken we een andere plug-in, ScrollTo, om soepel scrollen en handige positionering te bieden wanneer de gebruiker op de navigatielinks klikt.
Ik weet zeker dat je al bekend bent met de verschillende nieuwe elementen die met HTML5 zijn geïntroduceerd. In dit voorbeeld zullen we er twee gebruiken: en
. We beginnen met het volgende:
Een redelijk grote kop.
Lorem ipsum ...
We zullen onze navigatiebalk een expliciete breedte moeten geven. Maak het 28px breder dan het dekblad en duw het op zijn plaats met een negatieve linkermarge. Laten we het ook zacht afgeronde randen gebruiken border - * - radius
, evenals een aantal willekeurige opvulling.
nav positie: relatief; breedte: 928 px; opvulling: 2em; marge links: -14 px; grens-bovenkant-linker-straal: 14px 7px; border-top-right-radius: 14px 7px;
Vervolgens gaan we een ongeordende lijst met links in de navigatiebalk toevoegen en de items ervan instellen weergeven: inline-blok
om ze allemaal op één regel te zetten. We hebben geen kogels nodig, dus we gooien ook lijststijl: geen
in de mix.
nav li display: inline-block; lijststijl: geen;
Tot nu toe zou je zoiets als dit moeten hebben:
Nu, als alleen CSS ons toestond om meerdere pseudo-elementen te hebben (d.w.z.. :: Na :: na
), kunnen we de afgeronde randen van de navigatiebalk op een semantisch schone manier gemakkelijk voltooien. Maar dat kunnen we niet doen, dus we moeten twee niet-semantische toevoegen div
s aan het einde van de nav
. Geef ze de lessen nav-left
en nav-rechts
(of je zou ze iets fantasierijks kunnen noemen, zoals Castor en Pollux). Ze zijn 14px breed en 14px lang en zijn dat ook absoluut
ly 14px gepositioneerd vanaf het onderste uiteinde van de nav
.
Zoals hierboven te zien, de border-radius
familie van eigenschappen kan twee waarden voor elke hoek aannemen. Dat kunnen ook percentages zijn van de breedte van het element, wat best handig is - deze benadering maakt het mogelijk dat de randradius automatisch wordt aangepast aan wijzigingen in de afmetingen van de doos.
De kleine "schaduwen" waarmee de lintlook van de navigatiebalk wordt voltooid, worden gemaakt met ::na
pseudo-elementen. Hun breedte en hoogte, evenals hun grensstralen, worden ook ingesteld op basis van percentages.
/ * 'left' ruilen met 'right' voor de andere twee * / .nav-left position: absolute; links: 0; onder: -14px; breedte: 14 px; hoogte: 14 px; achtergrond: # 848a6a; grens-onder-linkerradius: 100% 50%; .nav-left :: after content: "; position: absolute; right: 0; width: 66%; height: 66%; background: # 000; border-top-left-radius: 100% 50%; border -bodem-links-radius: 100% 50%;
En we zijn hier klaar!
Nadat we de meest onmogelijke geometrie van rechtlijnige linten hebben weggedaan, laten we doorgaan.
Om het zwevende header-effect te bereiken, gebruiken we een jQuery-plug-in genaamd Waypoints, van Caleb Troughton. Het enige doel is om gebeurtenissen te activeren wanneer de gebruiker naar een bepaald element scrolt. Zoals u zult zien, is het uiterst eenvoudig, maar biedt het toch veel flexibiliteit - u kunt verschillende voorbeelden bekijken op de startpagina.
Voeg jQuery en Waypoints toe aan uw pagina en laten we aan de slag gaan!
De eerste denk dat je moet doen is een waypoint registreren door het .waypoint ()
methode op een element. Natuurlijk doet dit niets vanzelf - je zult een handler-functie moeten definiëren voor het evenement. De eenvoudigste manier om dit te doen is door die functie door te geven als een parameter voor .waypoint ()
.
Probeer het nu: voeg het volgende toe aan uw script en zie een bericht verschijnen als u voorbij de navigatiebalk bladert.
$ (function () // Wanneer de pagina is geladen, $ ('nav'). waypoint (// maak een waypoint-functie () alert ("Waypoint bereikt.");));
Nu, om het gewenste effect te bereiken, zullen de dingen noodzakelijkerwijs iets ingewikkelder worden. Ten eerste moeten we onze navigatiebalk in een container plaatsen, die ons werkelijke waypoint is, en dienen als een handige tijdelijke aanduiding (meer hierover hieronder).
Maak in uw CSS de volgende CSS-regel. (Als je bezig bent, verplaats je eventuele verticale marges naar nav
misschien wel voor de nav-container
)
.plakkerig positie: vast; boven: 0;
En we zijn klaar voor het goede deel! Verander de inhoud van je script naar het volgende:
$ (function () // Kijk op voorhand naar onze DOM-lookups var nav_container = $ (". nav-container"); var nav = $ ("nav"); nav_container.waypoint (handler: function (event, direction) nav.toggleClass ('sticky', direction == 'down');););
Oké, waar komt dit allemaal vandaan, vraag je je terecht af. Nou, je hebt waarschijnlijk door dat we een waypoint aan de nav-container
; alleen deze keer doen we het anders. In plaats van direct de handlerfunctie door te geven aan .waypoint ()
, we kapselen het in een object in. Op zichzelf maakt dit geen verschil: beide zijn volledig geldige manieren om hetzelfde te doen. Het object dat we passeren, kan echter verschillende andere optiewaarden bevatten, dus het gebruik ervan zorgt nu voor meer consistente code.
De handlerfunctie die we hebben gedefinieerd, ontvangt twee parameters: de eerste is de standaard jQuery evenement
object, wat hier niet van belang is. De tweede is Waypoints-specifiek: het is een string waarvan de waarde ook is 'Down'
of 'Up'
afhankelijk van de manier waarop de gebruiker aan het scrollen was toen ze het waypoint bereikten.
Nu is het weten van de manier waarop de gebruiker zich begeeft een heel belangrijk stukje informatie te geven, simpelweg omdat het ons in staat stelt om ander gedrag in beide richtingen uit te voeren. In de body van de handler-functie gebruiken we een relatief weinig bekende variant van jQuery's .toggleClass ()
methode, wat voor een handige afkorting zorgt: in deze syntaxis bepaalt de tweede parameter of de klasse aan het doelelement wordt toegevoegd of eruit wordt verwijderd. Wanneer de gebruiker naar beneden scrolt, de expressie === richting omlaag
evalueert naar waar
, dus onze navigatiebalk ontvangt de kleverig
klasse en plakt aan de bovenkant van de viewport. Zodra de gebruiker weer omhoog schuift, wordt de klasse verwijderd uit de navigatiebalk, die terugkeert naar zijn plaats. Probeer het nu.
Gaaf he? Als je echter langzaam langs het waypoint scrolt dat je zojuist hebt gemaakt, zul je waarschijnlijk merken dat de inhoud tijdens het passeren een beetje omhoog springt doordat de navigatiebalk uit de contentstroom wordt verwijderd. Behalve dat het er erg slordig uitziet, kan dergelijk gedrag mogelijk een deel van uw inhoud verbergen en de bruikbaarheid schaden. Gelukkig is alles wat je nodig hebt een eenvoudige oplossing - het toevoegen van de volgende code aan je handlerfunctie zorgt ervoor dat de sprong verdwijnt.
if (direction == 'down') nav_container.css ('height': nav.outerHeight ()); else nav_container.css ('height': 'auto');
Wat hier gebeurt, is vrij duidelijk: we gebruiken nav-container
als een tijdelijke aanduiding, zoals hierboven vermeld. Wanneer we naar beneden scrollen, breiden we de hoogte uit en blijft de onderstaande inhoud op zijn plaats. Er is echter een inhaalslag: om dit te laten werken zoals het is, moeten alle verticale marges die u mogelijk rondom de navigatiebalk wilt hebben, worden toegepast op nav-container
en niet aan de nav
.
Dus daar is het! We hebben een mooie vaste navigatiebalk, net zoals veel andere sites al doen. Show is voorbij, mensen ...
… of is het? Welnu, er is nog steeds een truc of twee die je misschien wilt zien, en die je misschien net voor de boeg zou gooien. Als dat het geval is, lees dan verder.
Als u erover nadenkt, zijn er veel gevallen waarin het triggeren van een gebeurtenis wanneer een element de uiterste rand van het kijkvenster bereikt, niet is wat u wilt doen. Gelukkig biedt Waypoints hiervoor een handige optie: compenseren
. Hier is hoe het eruit ziet:
nav.waypoint (handler: ..., offset: 50)
compenseren
stelt u in staat om het actuele waypoint op een variabele afstand vanaf de bovenkant van het element te creëren. Een positieve waarde triggert het waypoint wanneer de top van het element zich op de opgegeven afstand onder de bovenkant van de viewport bevindt en een negatieve waarde het waypoint activeert wanneer het element zover boven de bovenkant van de viewport staat (dwz de gebruiker is er ver voorbij gescrold ).
De waarde van offset kan een getal zijn (dat staat voor een vast aantal pixels), een tekenreeks die een percentage bevat (geïnterpreteerd als een percentage van de hoogte van het kijkvenster) of een functie die een aantal pixels retourneert. De laatste kan voor enige serieuze flexibiliteit zorgen en we zullen er later wat gebruik van maken. Laten we voorlopig vasthouden aan vaste waarden en kijken waar ze goed voor zijn.
Het eerste dat in je opkomt is het toevoegen van wat ruimte boven het plakkerige element. De ... gebruiken compenseren
variabele, dit is eenvoudig: voeg voor een 15-pixel offset vanaf de top toe offset: 15px
naar .waypoint ()
opties en verandering top: 0px
naar top: 15px
in de .kleverig
CSS-regel.
Als je ontwerp erom vraagt, kan een klein verloop boven de navigatiebalk ook een leuke touch zijn. Dit wordt eenvoudig bereikt door nog een andere toe te voegen div
binnen in de nav
, en schrijf een beetje CSS:
.sticky .nav-above position: absolute; top: -15px; left: 1em; rechts: 1em; hoogte: 15px; achtergrond: lineaire gradiënt (boven, rgba (255,255,255,1) 0%, rgba (255,255,255,0) 100%); / * voeg indien nodig gradiëntcode voor de cross-browser toe * /
Dit mooie subtiele stukje eye candy zou mooi werken in minimalistische ontwerpen.
Een ding dat Caleb zorgvuldig in Waypoints heeft opgenomen, is het dynamisch kunnen genereren van de offset van een waypoint, zoals zo:
nav.waypoint (handler: ..., offset: function () return - (nav.outerHeight () + 50);)
Dit stelt ons in staat om een handler te hebben die zou triggeren als de gebruiker al 50px voorbij de onderkant van het element is geschoven, zonder de hoogte vooraf te hoeven weten.
Notitie: Dergelijke procedureel gegenereerde offsets (evenals die gegeven als percentages), worden herberekend telkens wanneer het formaat van het venster wordt gewijzigd, nieuwe waypoints worden toegevoegd of de opties van een waypoint worden gewijzigd. Als u iets anders doet dat van invloed kan zijn op de posities van de waypoints (zoals het wijzigen van de DOM of pagina-indeling), moet u $ .Waypoints ( 'refresh')
daarna om de posities opnieuw te berekenen.
In het kader van onze zelfstudie is het gebruik van deze functionaliteit een vloeiende overgang van de navigatiebalk vanaf de bovenkant. Wees voorbereid - het volgende is het grootste stuk code tot nu toe. Er zou niets in moeten zitten waar je nog niet bekend mee bent, dus hier geldt:
var top_spacing = 15; var waypoint_offset = 50; nav_container.waypoint (handler: function (event, direction) if (direction == 'down') nav_container.css ('height': nav.outerHeight ()); nav.addClass ("sticky"). stop () .css ("top", -nav.outerHeight ()) .anim ("top": top_spacing); else nav_container.css ('height': 'auto'); nav.removeClass ("sticky") .stop () .css ("top", nav.outerHeight () + waypoint_offset) .anim ("top": "");, offset: function () return - (nav .outerHeight () + waypoint_offset););
Niet te shabby! Het is allemaal vrij standaard jQuery-tarief: zodra we het toevoegen of verwijderen kleverig
klasse voor de nav
, we overschrijven de verticale positie van het element met behulp van .css ()
, en dan .animeren ()
het tot wat het zou moeten zijn. De .hou op()
dient om mogelijke bugs te voorkomen door jQuery's event-wachtrij te wissen.
Dit heeft echter een klein neveneffect: aangezien de code de verticale positie van het navigatie-element effectief overneemt, kunt u net zo goed de top: 15px
verklaring van uw CSS. Als u deel uitmaakt van een groot project, met afzonderlijke mensen die werken aan ontwerp en front-end scripting, kan dit een probleem vormen, omdat u dergelijke hacks gemakkelijk kunt kwijtraken. Om u dit te laten weten, bestaan er plug-ins, zoals de uitstekende jQuery.Rule van Ariel Flesler, die kan worden gebruikt om de kloof tussen scripts en stylesheets te overbruggen. Je zult zelf moeten beslissen of je zoiets nodig hebt.
Je zou zeker een vergelijkbaar effect kunnen bereiken met CSS @keyframes
in plaats daarvan, maar er is veel minder ondersteuning voor hen (en veel voorvoegsels van leveranciers), ze zijn minder flexibel en de 'up'-animatie zou een groot nee-nee zijn. Omdat we niet het pad van progressieve verbetering verlaten, is er geen reden om niet vast te houden aan de robuuste functionaliteit van jQuery.
Mogelijk moet u wijzigen welk item wordt gemarkeerd wanneer de lezer langs verschillende secties van uw pagina komt. Met Waypoints is dit vrij eenvoudig te bereiken. U moet het volgende aan uw script toevoegen:
$ (function () ... // kopie van hier ... var sections = $ ('section'); var navigation_links = $ ('nav a'); sections.waypoint (handler: function (event, direction) // handler-code, offset: '35% '); // ... om hier);
Deze keer gebruiken we een offset die wordt uitgedrukt als een percentage van de hoogte van het venster. In feite betekent dit dat de denkbeeldige regel die ons script vertelt welke sectie momenteel wordt bekeken ongeveer een derde van de bovenkant van de viewport wordt geplaatst - precies waar de kijker naar zou kijken als hij een lange tekst leest. Een robuustere oplossing zou een functie kunnen gebruiken om zich aan te passen aan veranderingen in de hoogte van de navigatiebalk.
De code die we gaan gebruiken in onze handlerfunctie is echter iets minder vanzelfsprekend. Hier is het:
var active_section; active_section = $ (this); if (direction === "up") active_section = active_section.prev (); var active_link = $ ('nav a [href = "#' + active_section.attr (" id ") + '"]'); navigation_links.removeClass ( "geselecteerd"); active_link.addClass ( "geselecteerd");
Ten eerste moeten we weten welk gedeelte momenteel wordt bekeken. Als we naar beneden scrollen, is de sectie waartoe het waypoint behoort dezelfde als die wordt geactiveerd. Omhoog scrollen langs een waypoint betekent echter dat het vorige gedeelte in beeld is gebracht - dus gebruiken we .prev ()
om het te selecteren. Vervolgens verwijderen we de gekozen
klasse van alle links in de navigatiebalk, voordat deze opnieuw wordt toegepast op degene wiens href
attribuut komt overeen met de ID kaart
van het momenteel actieve gedeelte.
Dit werkt best goed; als je verder wilt gaan dan het toevoegen en verwijderen van klassen, wil je misschien een plug-in zoals LavaLamp bekijken.
Op een gegeven moment is het u misschien opgevallen dat als u op de links in de navigatiebalk klikt, de bovenkant van het gedeelte helemaal bovenaan het browservenster wordt geplaatst. Dit is contra-intuïtief genoeg als er niets dat gedeelte van het scherm verduistert; nu we daar een navigatiebalk hebben, wordt het een enorme ergernis. Dit is waar de ScrollTo van Ariel Flesler te hulp komt. Voeg het toe aan uw pagina en voeg vervolgens de volgende code toe:
navigation_links.click (functie (event) $ .scrollTo ($ (this) .attr ("href"), duration: 200, offset: 'left': 0, 'top': - 0.15 * $ (window) .hoogte() ); );
(natuurlijk gaat die code boven de laatste accolade!)
Hoewel er betere manieren zijn om een functie te koppelen aan klikgebeurtenissen, blijven we bij de meest eenvoudige: .Klik()
. De .scrollTo ()
methode wordt aangeroepen op een manier die sterk lijkt op .waypoint ()
. Er zijn twee parameters voor nodig: een schuifdoel en een object met verschillende opties, die in dit geval vrij duidelijk zijn. De geklikte link's href
attribuut werkt netjes als een schuifdoel en de uitdrukking die als topverschuiving wordt gebruikt, plaatst het doel op 15% van de hoogte van het kijkvenster.
En het lijkt erop dat we klaar zijn. Ik heb je laten kennismaken met de handige kleine plugin die Waypoints is, en we hebben enkele gebruikscasussen besproken die je een idee zouden moeten geven van de verschillende dingen die je ermee zou kunnen bereiken. We hebben ook een veel intuïtiever schuifgedrag geïmplementeerd dat bij onze navigatie past. Gooi wat Ajax in de mix en je bent op weg om een soort naadloze, meeslepende webervaring op te bouwen die de toekomst van het web gaat worden ... nou ja, waarschijnlijk is het een korte tijd trendy en wordt het dan alledaags, web-veteranen nostalgisch maken over hoe de dingen vroeger waren. Maar goed, zo gaan de dingen.
Wat betreft linten, hun grootste nadeel is dit: ze zijn slechts een illusie. De zijkanten van het lint gaan eigenlijk niet langs de randen van de container; ze verschijnen alleen op die manier, wat vrij duidelijk wordt als het lint over een element gaat dat uitsteekt vanaf de rand van de pagina.
Vanwege de werking van z-index lijkt er geen eenvoudige manier te zijn om dit conflict op te lossen, met uitzondering van het vermijden van dit conflict. Echter, met enige verbeeldingskracht, evenals een basiskennis van jQuery, zou je een manier kunnen bedenken waarop deze elementen kunnen worden gebruikt ga uit de richting van het lint als het hen nadert. Dit doen is echter buiten het bestek van deze tutorial; hopelijk kan ik het je vroeg of laat laten zien in de vorm van een snelle tip, hier of op Nettuts +. Blijf kijken!