Μερικές φορές μια ιδέα ενός σχεδιαστή που μοιάζει ιδιόρρυθμη, μετατρέπεται σε κάτι που πραγματικά απολαμβάνεις να υλοποιείς. Αυτό ακριβώς συνέβη με αυτό το πρότζεκτ: στήλες περιεχομένου που γλιστρούν σε αντίθετες κατευθύνσεις καθώς ο χρήστης κάνει scroll.

Live demo (CodePen): το εφέ σέβεται τις ρυθμίσεις μειωμένης κίνησης, οπότε θα χρειαστεί να ενεργοποιήσετε την κίνηση για να το δείτε. Κατά τη στιγμή της γραφής, λειτουργεί σε Chrome και Safari.

Η σύγχρονη CSS το καθιστά εκπληκτικά απλό — τα scroll-driven animations είναι ο πρωταγωνιστής εδώ. Ας δούμε βήμα-βήμα την προσέγγιση. Ίσως βρείτε και εσείς έναν διαφορετικό τρόπο να το κάνετε.

Η Δομή HTML

Τρία επίπεδα φωλιάσματος: ένα γονικό container (.opposing-columns), παιδικές στήλες (.opposing-column), και items μέσα σε κάθε στήλη (.opposing-item).

<div class="opposing-columns">
  <div class="opposing-column">
    <div class="opposing-item">...</div>
    <div class="opposing-item">...</div>
  </div>
  <div class="opposing-column">
    <div class="opposing-item">...</div>
  </div>
  <div class="opposing-column">
    <div class="opposing-item">...</div>
  </div>
</div>

Αυτό είναι όλο. Η CSS αναλαμβάνει τα υπόλοιπα.

Responsive Ρύθμιση

Το εφέ έχει νόημα μόνο σε μεγαλύτερες οθόνες όπου υπάρχει αρκετός οριζόντιος χώρος. Το τυλίγουμε όλο σε ένα media query:

@media screen and (width >= 50rem) {
  .opposing-columns {
    display: flex;
    gap: 2rem;
    max-inline-size: min(90dvi, 50rem);
    margin-inline: auto;
  }
}

Δημιουργώντας την Ψευδαίσθηση Μάσκας

Τα items στις εξωτερικές στήλες κινούνται προς τα πάνω στο scroll, ενώ αυτά στην κεντρική στήλη κινούνται προς τα κάτω. Για να εξασθενίζουν καθώς διασχίζουν τα όρια του container, χρησιμοποιούμε pseudo-elements με gradients — χωρίς κόλπα opacity.

Αρχικά, ορίζουμε μια μεταβλητή χρώματος φόντου στο :root:

:root {
  --opposing-bg: lightcyan;
  --opposing-mask: 3rem;
  background-color: var(--opposing-bg);
}

Στη συνέχεια, εφαρμόζουμε :before και :after στο γονικό στοιχείο με το ίδιο χρώμα φόντου και z-index: 1 για να βρίσκονται πάνω από τις στήλες:

.opposing-columns {
  position: relative;
  margin-block: var(--opposing-mask, 3rem);

  &:before,
  &:after {
    content: "";
    position: absolute;
    inset-inline: 0;
    block-size: calc(var(--opposing-mask) * 3);
    pointer-events: none;
    z-index: 1;
  }
}

Τώρα τα gradients:

  • Top pseudo (:before): από συμπαγές φόντο σε διαφανές, από πάνω προς τα κάτω.
  • Bottom pseudo (:after): από διαφανές σε συμπαγές φόντο, από κάτω προς τα πάνω.
.opposing-columns {
  &:before {
    background-image: linear-gradient(
      to bottom,
      var(--opposing-bg) var(--opposing-mask),
      transparent
    );
    inset-block-start: calc(var(--opposing-mask) * -1);
  }

  &:after {
    background-image: linear-gradient(
      to top,
      var(--opposing-bg) var(--opposing-mask),
      transparent
    );
    inset-block-end: calc(var(--opposing-mask) * -1);
  }
}

Τα items γλιστρούν κάτω από αυτές τις μάσκες καθώς κάνετε scroll, δημιουργώντας ένα καθαρό fade στα πάνω και κάτω άκρα του container.

Πρακτικές Σκέψεις για Επιχειρήσεις σε Κύπρο & ΕΕ

  • Απόδοση: τα scroll-driven animations εκτελούνται στο compositor thread — χωρίς janks από JavaScript. Αυτό έχει σημασία για χρήστες κινητών με 4G στη Λεμεσό ή τη Λευκωσία.
  • GDPR & Προσβασιμότητα: το demo σέβεται το prefers-reduced-motion. Πάντα να συμπεριλαμβάνετε αυτόν τον έλεγχο για να αποφεύγετε παραβιάσεις των οδηγιών προσβασιμότητας της ΕΕ.
  • Πολύγλωσσες ιστοσελίδες (EN/RU/EL): αυτή η τεχνική CSS λειτουργεί ανεξάρτητα από την εναλλαγή γλώσσας ή τις διατάξεις RTL (χρησιμοποιήστε inset-inline και inset-block όπως κάναμε).
  • Εκτίμηση κόστους: για ένα custom component σαν αυτό, υπολογίστε 2–4 ώρες ανάπτυξης. Σε συνδυασμό με μια πλήρη κατασκευή ιστοσελίδας (5–10 σελίδες), τα τυπικά κόστη από ένα web studio στην Κύπρο κυμαίνονται από €1.500–€3.500.