Slider mit gleitenden Hintergründen

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Eines der vielen super schönen Designmerkmale der Yahoo! Weather App für iOS ist der Übergang zwischen den Stadtbildschirmen. Das Hintergrundbild bewegt sich nicht einfach weg, wenn der Bildschirm von einem zum nächsten wechselt, sondern das Hintergrundbild gleitet selbst. Es scheint, als würde es einen Teil des "alten" Bildschirms verdecken und mehr vom "neuen" Bildschirm enthüllen, je näher es zur vollständigen Ansicht ist.

Versuchen wir, das im Web nachzubilden.

Das HTML

Wie jeder Slider besteht er aus drei Hauptkomponenten

  • Der Container, der alles in Form hält
  • Ein gleitender Container, der so breit ist wie alle Slides nebeneinander
  • Jeder einzelne Slide-Container

Wir werden uns nicht allzu sehr um den Inhalt innerhalb des Slides kümmern. Ich füge nur die Temperatur hinzu, um zu zeigen, dass jeder Slide tatsächlich Inhalt darüber aufnehmen kann.

<div class="slider" id="slider">
  <div class="holder">
    <div class="slide" id="slide-0"><span class="temp">74°</span></div>
    <div class="slide" id="slide-1"><span class="temp">64°</span></div>
    <div class="slide" id="slide-2"><span class="temp">82°</span></div>
  </div>
</div>

Der Container könnte ein <section> sein, die Slides könnten <article> sein. Das hängt wirklich davon ab. Ich überlasse Ihnen die semantischen Entscheidungen für Ihre eigenen Bedürfnisse.

Der Layoutplan sieht so aus

Das CSS

Der "Slider" (visueller Container) und die Slides müssen explizit die gleiche Größe haben. Wir verwenden hier Pixel, aber Sie könnten es mit jeder Einheit umsetzen.

.slider {
  width: 300px;
  height: 500px;
  overflow-x: scroll;
}
.slide {
  float: left;
  width: 300px;
  height: 500px;
}

Das Floaten dieser Slides nach links wird sie nicht nebeneinander aufreihen, da das Elternelement der Slides nicht breit genug ist, um dies zuzulassen. Das ist einer der Gründe, warum wir das Holder-Element benötigen. Es wird 300% breit sein (Anzahl der Slides × 100%), was genau drei Slides fasst.

.holder {
  width: 300%;
}

Jeder unserer Slides hat eine eindeutige ID. Das ist nützlich, denn wenn wir wollen, können wir Ankerlinks erstellen, die auf diese IDs verweisen und der Slider wird zu diesen Slides "springen". Wir werden JavaScript hinzufügen, um das eigentliche "Gleiten" durchzuführen, aber unser Slider wird auch ohne das funktionieren. IDs machen das möglich, also verwenden wir sie hier, um einige schöne Hintergrundbilder einzufügen.

#slide-0 {
  background-image: url(http://farm8.staticflickr.com/7347/8731666710_34d07e709e_z.jpg);
}
#slide-1 {
  background-image: url(http://farm8.staticflickr.com/7384/8730654121_05bca33388_z.jpg);
}
#slide-2 {
  background-image: url(http://farm8.staticflickr.com/7382/8732044638_9337082fc6_z.jpg);
}

Mit all dem an Ort und Stelle nimmt unser Layout Gestalt an

Das CSS (schwarzes Ausblenden)

Als kleines Detail kann die in Weiß gesetzte Temperatur Gefahr laufen, je nach Foto dahinter nicht sichtbar zu sein. Um sicherzustellen, dass sie sichtbar ist, können wir das Foto zum unteren Rand hin subtil schwarz überblenden lassen. Ein Pseudo-Element eignet sich dafür gut.

.slide:before {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 40%;
  background: linear-gradient(transparent, black);
}

Eine Erklärung mit Bildern ist hier angebracht

Das JavaScript (gleitende Hintergründe)

Wir werden hier jQuery verwenden, weil wir das Leben lieben. Unser Ziel ist es, die `background-position` der Slides beim Scrollen anzupassen. Wir können `background-position` in Prozent in CSS einstellen, aber das allein bewirkt nicht den coolen Versteck/Mehr-Enthüll-Effekt, den wir suchen. Basierend auf der gescrollten Menge (die wir in JavaScript messen können), passen wir die `background-position` an. Allein würde das ungefähr so aussehen

$("#slider").on("scroll", function() {
  $(".slides").css({
    "background-position": $(this).scrollLeft()/6-100+ "px 0"
  });  
});

Die "6" und "-100" sind magische Zahlen. Nicht magische CSS-Zahlen, die anfällig für Fehler sind, sondern traditionelle magische Zahlen. Nur ein paar Zahlen, die zufällig den Effekt bewirken. Ein Nachteil vielleicht, aber keine große Sache. Design-Sachen sind manchmal so. Vielleicht ist es am besten, einen Kommentar im Code dazu zu hinterlassen. Diese speziellen Zahlen basieren auf den von mir verwendeten Bildern, ihrer Größe und dem, was gut aussah.

Der Effekt, den wir hier erzielen wollen, ist das Verschieben des Hintergrunds

Beachten Sie, dass weniger vom gelben Straßenbahnwagen sichtbar ist, wenn sich der Slide fast außerhalb des Sichtfelds befindet.

Das JavaScript (Strukturvermittlung)

Dieser kleine JavaScript-Schnipsel sieht ohne eine Struktur dahinter einsam aus. Ein Slider ist ein guter Anlass, sich eine einfache Möglichkeit zur Strukturierung von JavaScript anzusehen.

Wir können alles Slider-bezogene in ein Objekt packen.

var slider = {

};

Dann gruppieren wir die zusammengehörigen Elemente in einem Bereich, binden unsere Ereignisse zusammen und schreiben kleine Funktionen, die sehr spezifische Dinge tun.

var slider = {
  
  el: {
    slider: $("#slider"),
    allSlides: $(".slide")
  },
 
  init: function() {
    // manual scrolling
    this.el.slider.on("scroll", function(event) {
      slider.moveSlidePosition(event);
    });
  },
  
  moveSlidePosition: function(event) {
    // Magic Numbers
    this.el.allSlides.css({
      "background-position": $(event.target).scrollLeft()/6-100+ "px 0"
    });  
  }
  
};

slider.init();

Das HTML (Hinzufügen von Navigation)

Das Hinzufügen von Swipe-Funktionen wäre super (super) süß (Hinweis). Aber vorerst fügen wir kleine klickbare Links hinzu, um Slides zu wechseln, anstatt uns auf die Scrollleiste zu verlassen. Sie könnten die Scrollleiste im echten Leben sogar entfernen (einfach `overflow: hidden;` auf dem Container). Was wir brauchen, sind Ankerlinks, die auf die IDs der einzelnen Slides verweisen.

<nav class="slider-nav">
  <a href="#slide-0" class="active">Slide 0</a> 
  <a href="#slide-1">Slide 1</a> 
  <a href="#slide-2">Slide 2</a> 
</nav>

Gestalten Sie diese, wie Sie möchten. Für die Demo mache ich sie zu kleinen grauen Kreisen mit verstecktem Text.

Das JavaScript (Hinzufügen von Navigation)

Unsere Struktur ist jetzt nützlicher. Wir fügen einfach ein paar Elemente hinzu, mit denen wir arbeiten, ein neues Ereignis, das wir beobachten (Klicks auf die Navigation), und schreiben eine kleine Funktion, um dieses Ereignis zu behandeln.

Wir wissen, wie weit wir die Scrollposition animieren müssen, wenn ein Navigationslink geklickt wird, basierend auf der ID im Link selbst. Der Link könnte `href="slide-1"` sein, von dem wir leicht "1" extrahieren können. Dann ist die Position, zu der wir scrollen müssen, (1 × Breite des Slides), also 300 in unserem Fall. Diesen Wert von 300 speichern wir direkt im JavaScript.

var slider = {
  
  el: {
    slider: $("#slider"),
    allSlides: $(".slide"),
    sliderNav: $(".slider-nav"),
    allNavButtons: $(".slider-nav > a")
  },
  
  timing: 800,
  slideWidth: 300, // could measure this
  
  init: function() {
    // You can either manually scroll...
    this.el.slider.on("scroll", function(event) {
      slider.moveSlidePosition(event);
    });
    // ... or click a thing
    this.el.sliderNav.on("click", "a", function(event) {
      slider.handleNavClick(event, this);
    });
  },
  
  moveSlidePosition: function(event) {
    // Magic Numbers
    this.el.allSlides.css({
      "background-position": $(event.target).scrollLeft()/6-100+ "px 0"
    });  
  },
  
  handleNavClick: function(event, el) {
    // Don't change URL to a hash, remove if you want that
    event.preventDefault();

    // Get "1" from "#slide-1", for example
    var position = $(el).attr("href").split("-").pop();
    
    this.el.slider.animate({
      scrollLeft: position * this.slideWidth
    }, this.timing);
    
    this.changeActiveNav(el);
  },
  
  changeActiveNav: function(el) {
    // Remove active from all links
    this.el.allNavButtons.removeClass("active");
    // Add back to the one that was pressed
    $(el).addClass("active");
  }
  
};

slider.init();

Wir haben eine "active"-Klasse auf den Navigationslinks, um sie in CSS visuell anzuzeigen, welcher Slide aktiv ist. Wir behandeln dies, indem wir "active" von allen Links entfernen und dann dem geklickten wieder hinzufügen.

Demo!

Check out this Pen!