← Όλα τα άρθρα

Dark Reader: `darkreader-lock` αντί για `color-scheme`

Το Dark Reader περνάει δύο φορές από sites που έχουν ήδη dark theme, αδιαφορώντας για το `color-scheme`. Η λύση είναι ένα μόνο meta tag: το `darkreader-lock`.

Dark Reader: `darkreader-lock` αντί για `color-scheme`

Το site μου έχει δικό του dark theme. Σχεδόν μαύρο φόντο, ζεστές πορτοκαλί πινελιές, ένα grain effect που μου πήρε αρκετή ώρα να φτιάξω σωστά. Light mode δεν υπάρχει. Οπότε όταν ένας φίλος μου είπε ότι το site «φαίνεται χαλασμένο», το παράβλεψα — μέχρι που μου έστειλε screenshot. Τα χρώματα αντεστραμμένα, το grain χαοτικό, το πορτοκαλί κάτι θολό και άσχημο. Το site ήταν μια χαρά. Η επέκταση του browser του, όχι.

Φταίει το Dark Reader, μια δημοφιλής επέκταση που βάζει dark mode σε κάθε σελίδα που επισκέπτεσαι. Στην προεπιλεγμένη λειτουργία dynamic mode ξαναχρωματίζει ολόκληρη τη σελίδα on the fly — αντιστρέφει φόντα, αλλάζει κείμενα. Σε ένα site που έχει ήδη dark theme, αυτό σημαίνει διπλή επεξεργασία ενός ήδη σκοτεινού σχεδιασμού. Το αποτέλεσμα φαίνεται πραγματικά σπασμένο.

Η λάθος λύση που δοκίμασα πρώτα

Η πρώτη μου σκέψη ήταν το color-scheme. Η CSS ιδιότητα και το αντίστοιχο meta tag λένε στον browser «αυτή η σελίδα είναι φτιαγμένη για dark color scheme». Στο Next.js 15 το βάζεις καθαρά μέσω του export viewport:

// app/layout.tsx
export const viewport: Viewport = {
  colorScheme: 'dark',
}

Αυτό βγάζει <meta name="color-scheme" content="dark"> και ορίζει την CSS ιδιότητα στο :root. Είναι η σωστή κίνηση — λέει στον browser να χρησιμοποιεί σκοτεινό native UI chrome (scrollbars, form inputs, system dialogs). Αλλά στο Dark Reader δεν κάνει απολύτως τίποτα. Το Dark Reader δεν κοιτάει το color-scheme. Έχει τη δική του λογική ανίχνευσης και στη dynamic ρύθμιση θα επεξεργαστεί τη σελίδα ό,τι κι αν γράψεις.

Το επιβεβαίωσα χάνοντας είκοσι λεπτά. Η επέκταση συνέχιζε να πυροδοτείται. Το site συνέχιζε να φαίνεται στραβό.

Η σωστή λύση: darkreader-lock

Το Dark Reader έχει έναν επίσημο μηχανισμό εξαίρεσης: το meta tag darkreader-lock. Μόλις η επέκταση το δει στο head του document, απενεργοποιείται τελείως για εκείνη τη σελίδα. Ένα tag. Χωρίς JavaScript. Χωρίς CSS hacks.

Στο Next.js 15 το πιο καθαρό σημείο να το βάλεις είναι το πεδίο other του Metadata API, στο app/layout.tsx:

// app/layout.tsx
import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'Kyriakos Kaitezidis',
  description: '...',
  // ... rest of your metadata
  other: {
    'darkreader-lock': 'darkreader-lock',
  },
}

Το Next.js αποδίδει κάθε καταχώρηση του other ως <meta name="key" content="value"> στο head. Η επέκταση βλέπει <meta name="darkreader-lock" content="darkreader-lock"> και σταματά. Τίποτα άλλο δεν χρειάζεται.

Κράτησε το color-scheme ούτως ή άλλως

Άφησα το viewport.colorScheme: 'dark' export στη θέση του. Δεν σταματά το Dark Reader, αλλά έχει τον δικό του λόγο ύπαρξης: ενημερώνει το rendering engine του browser ότι η σελίδα είναι φτιαγμένη για σκοτεινό περιβάλλον, κάτι που επηρεάζει native UI controls, system scrollbars και τον τρόπο που αποδίδονται τα αδρανή input fields. Είναι ένα semantic hint στην πλατφόρμα — όχι kill-switch για το Dark Reader. Τα δύο συνυπάρχουν χωρίς πρόβλημα και εξυπηρετούν διαφορετικά πράγματα.

Πότε ΔΕΝ πρέπει να το κάνεις

Αποκλείεις το Dark Reader εδώ γιατί το site σου ήδη προσφέρει μια ολοκληρωμένη dark εμπειρία. Αν βάλεις αυτό το tag σε ένα site χωρίς dark theme, εμποδίζεις ενεργά χρήστες που βασίζονται στην επέκταση να έχουν μια σκοτεινή έκδοση. Αυτό είναι ενοχλητικό. Το darkreader-lock αξίζει μόνο αν έχεις κάνει τη δουλειά — αν έχεις πραγματικό dark theme, έχεις κάθε λόγο να το προστατεύσεις από διπλή επεξεργασία.

Τι έκανα deploy

Η διόρθωση μπήκε στο app/layout.tsx σαν μια απλή προσθήκη πεδίου. Καμία νέα εξάρτηση, κανένα runtime κόστος. Οι χρήστες του Dark Reader βλέπουν πλέον το site ακριβώς όπως σχεδιάστηκε. Το grain effect κρατάει. Το πορτοκαλί μένει πορτοκαλί.

Αυτό είναι το είδος του bug που βολεύει να το πετάξεις στον χρήστη — «είναι η επέκτασή σου, δεν φταίω εγώ». Αλλά αν κάποιος με Dark Reader επισκεφτεί το site και το δει σπασμένο, αυτό παραμένει δικό μου πρόβλημα. Η λύση υπάρχει και στήνεται σε τριάντα δευτερόλεπτα.

FAQ

Τι είναι το meta tag darkreader-lock; Είναι επίσημος μηχανισμός εξαίρεσης που παρέχει η ίδια η επέκταση Dark Reader. Μόλις βρει <meta name="darkreader-lock"> στο head του document, σταματά να κάνει dynamic recoloring σε εκείνη τη σελίδα.

Σταματά το color-scheme: dark το Dark Reader; Όχι. Η CSS ιδιότητα color-scheme και το αντίστοιχο meta tag είναι hints προς το rendering engine του browser — επηρεάζουν native UI controls και system chrome, όχι επεκτάσεις τρίτων. Το Dark Reader τα αγνοεί και εφαρμόζει το dynamic mode ανεξάρτητα.

Πώς προσθέτω το darkreader-lock στο Next.js 15 App Router; Βάλ' το στο πεδίο other του root export const metadata στο app/layout.tsx: other: { 'darkreader-lock': 'darkreader-lock' }. Το Next.js το εκπέμπει ως κανονικό meta tag στο head.

Πρέπει κάθε site να χρησιμοποιεί το darkreader-lock; Όχι. Μόνο αν έχεις ήδη πλήρες dark theme. Αν το βάλεις σε site χωρίς dark mode, εμποδίζεις χρήστες που εξαρτώνται από το Dark Reader να έχουν μια αξιοπρεπή dark εμπειρία — και αυτό δεν αξίζει τον κόπο.