Come ho costruito un cruciverba CSS puro

Come ho costruito un cruciverba CSS puro

Cruciverba CSS

Recentemente ho creato un file cruciverba CSS puro implementato utilizzando la griglia CSS che non necessita di JavaScript per funzionare. Ha guadagnato molto interesse abbastanza rapidamente su CodePen. Al momento della stesura di questo documento, ha più di 350 cuori e oltre 24.000 visualizzazioni di pagina!

Il grande CSS Grid Garden il tutorial mi ha ispirato a creare qualcosa con le funzionalità di layout a griglia. Mi chiedevo se queste funzionalità potessero essere messe a frutto nella costruzione di un cruciverba, poi ho pensato, proviamo a creare il tutto senza usare JavaScript.

Costruire la scheda / griglia

Quindi, per prima cosa, creiamo la scheda stessa!

Ho finito con la seguente struttura di base, con commenti HTML inclusi per mostrare ciò che le diverse sezioni realizzeranno:

<div class="crossword-board-container">

  <div class="crossword-board">

    

    <div class="crossword-board crossword-board--highlight crossword-board--highlight--across">
      
    </div>

    <div class="crossword-board crossword-board--highlight crossword-board--highlight-down">
      
    </div>

    <div class="crossword-board crossword-board--labels">
      
    </div>

    <div class="crossword-clues">

      <dl class="crossword-clues__list crossword-clues__list--across">
        
      </dl>

      <dl class="crossword-clues__list crossword-clues__list--down">
        
      </dl>

    </div>

  </div>

</div>

Questo mette il nostro scheletro di base in posizione in modo da poter aggiungere più elementi e iniziare a disegnare le cose.

Utilizzo di elementi del modulo per i quadrati

Il cruciverba che sto creando è una griglia 13 × 13 con 44 spazi vuoti, quindi devo crearne 125 input elementi ciascuno con il proprio ID nel formato itemrow number-column number, ie item4-12. Ecco come apparirà la griglia:

Cruciverba vuoto

Ciascuno degli input avrà un file minlength e maxlength di "1" per emulare il comportamento di un cruciverba (cioè una lettera per quadrato). Ogni ingresso avrà anche l'estensione required attributo in modo che venga utilizzata la convalida del modulo HTML5. Approfitto di tutti questi attributi HTML5 utilizzando CSS.

Utilizzo del selettore di pari livello generale

Gli elementi di input sono disposti visivamente in gruppi (esattamente come è un cruciverba). Ogni gruppo di elementi di input rappresenta una parola nel cruciverba. Se ciascuno degli elementi in quel gruppo è valido (che può essere verificato utilizzando il file :valid pseudo selettore), quindi possiamo usare CSS per applicare lo stile a un elemento che appare in seguito nel DOM (utilizzando un selettore CSS avanzato chiamato selettore di pari livello generale) che indicherà che la parola è corretta.

A causa di come funzionano i selettori di pari livello e di come funzionano i CSS in generale, questo elemento deve apparire in un secondo momento nel DOM. I CSS possono applicare lo stile solo agli elementi che si trovano dopo l'elemento attualmente selezionato. Non può guardare indietro nel DOM (o in alto nell'albero DOM) e applicare uno stile a qualcosa prima dell'elemento corrente (al momento almeno comunque).

Ciò significa che posso usare il file :valid pseudo-classe per definire lo stile di elementi validi:

.input:valid 
  border: 2px solid green;

.input:invalid 
  border: 2px solid red;

Vedi la penna Esempio di pseudo selettore valido di Zentica (@SitePoint) su CodePen.

Per modellare un elemento in seguito nel DOM che è un fratello di un altro elemento, posso usare il selettore ~ ​​(tilde / general sibling), ad es. A ~ B. Questo selettore selezionerà tutti gli elementi che corrispondono a B, che sono un fratello di A e appariranno dopo A nel DOM. Per esempio:

#input1:valid ~ #input2:valid ~ #input3:valid ~ #input4:valid ~ #input5:valid ~ .valid-message 
  display: block;

Con questo codice, se tutti questi elementi di input sono validi, il file valid-message l'elemento verrà visualizzato.

Vedi la penna Utilizzo del selettore di pari livello per visualizzare un messaggio di Zentica (@SitePoint) su CodePen.

Il selettore del fratello generale è estremamente utile qui. Per far funzionare il cruciverba, dovevo assicurarmi che tutto fosse disposto in un modo che mi permettesse di sfruttare il selettore generale dei fratelli.

L'esempio di cruciverba finito utilizza la tecnica sopra, a partire dalla riga 285. L'ho separato nel blocco di codice qui sotto:

#item1-1:valid ~ #item1-2:valid ~ #item1-3:valid ~ 
#item1-4:valid ~ #item1-5:valid ~ #item1-6:valid ~ 
.crossword-board--highlight .crossword-board__item-highlight--across-1 
  opacity: 1;

Questa parte del CSS garantisce che se tutti questi elementi di input sono validi, allora l'opacità del file .crossword-board__item-highlight--across-1 l'elemento verrà modificato. .crossword-board--highlight è un fratello di tutti gli elementi di input e .crossword-board__item-highlight--across-1 è figlio di .crossword-board--highlight quindi è selezionabile con CSS!

Indicare le risposte corrette

Ogni risposta del cruciverba (cioè un gruppo di elementi di input) ha un corrispondente "indicatore di risposta corretta" (.crossword-board__item-highlight--across-clue number) elemento della griglia. Questi elementi della griglia vengono posizionati dietro gli elementi di input sull'asse z e vengono nascosti utilizzando opacity: 0. Quando viene inserita una parola corretta, viene visualizzato l'elemento della griglia dell'indicatore di risposta corretta modificando il opacity per 1, come dimostra lo snippet del selettore di pseudo-classe sopra.

Cruciverba con parola incompleta

Cruciverba con parola completata

Questa tecnica viene ripetuta per ogni gruppo di "parole" di elementi di input. Quindi questo significa creare manualmente ciascuna regola CSS per ciascuno degli elementi di input nel gruppo di parole e quindi selezionare l'elemento della griglia dell'indicatore di risposta corretto corrispondente. Come puoi immaginare, questo fa sì che il CSS diventi grande velocemente!

Quindi l'approccio logico sarebbe creare tutte le regole CSS che mostrano / nascondono gli elementi della griglia dell'indicatore di risposta corretta per tutte le risposte indizio orizzontali (trasversali). Quindi faresti lo stesso per le risposte indizio verticale.

Sfide del sistema di rete

Se, come me, stai cercando di utilizzare il meno CSS possibile, ti renderai presto conto che non puoi avere aree della griglia sovrapposte all'interno dello stesso sistema di griglia senza doverlo dichiarare esplicitamente. Possono sedersi solo uno accanto all'altro (1 in orizzontale e 1 in basso condividono un quadrato in alto a destra della lavagna e questo non è possibile quando si utilizza una griglia CSS per disporre tutti gli elementi dell'indicatore di risposta corretta).

La soluzione è racchiudere ogni elemento della griglia dell'indicatore di risposta corretta orizzontale (attraverso) nel proprio sistema di griglia e ogni elemento della griglia dell'indicatore di risposta corretta verticale (in basso) in un altro. In questo modo posso ancora usare i CSS per selezionarli (usando il selettore di pari livello generale), e non interferiranno tra loro e rovineranno il layout delle griglie.

Gli elementi CSS Grid Layout agiscono in modo simile agli elementi inline-block. Ciò significa fondamentalmente che se specifichi due elementi della griglia per occupare lo stesso spazio, il secondo elemento scorrerà attorno al primo elemento e apparirà dopo di esso nella griglia.

Vedi la penna Esempio di modulo layout griglia di Zentica (@SitePoint) su CodePen.

Nell'esempio precedente, il primo elemento della griglia è largo sette colonne e si estende dalla prima alla settima colonna. Il secondo elemento della griglia deve iniziare dalla quarta colonna e si estende fino alla nona colonna. Alla griglia CSS non piace, quindi la avvolge nella riga successiva. Anche se specifichi grid-row: 1/1 nel secondo elemento, questo avrà la priorità e quindi sposterà il primo elemento della griglia nella seconda riga.

Come spiegato sopra, ho evitato questo problema avendo più griglie per elementi orizzontali e verticali. Questa situazione può essere evitata specificando l'estensione di righe e colonne per ogni elemento, ma ho usato il metodo sopra per ridurre la quantità di CSS e anche per avere una struttura HTML più gestibile.

Verifica di immissione di lettere valide

Ogni elemento di input ha un'estensione pattern attributo con un'espressione regolare come valore. L'espressione regolare corrisponde a una lettera maiuscola o minuscola per quel quadrato:

<input id="item1-1" class="crossword-board__item"
       type="text" minlength="1" maxlength="1"
       pattern="^[sS]1$" required value="">

Questo non era l'ideale perché le risposte sono nell'HTML. Volevo nascondere le risposte nel CSS, ma non sono riuscito a trovare un modo per farlo con successo. Ho provato la seguente tecnica:

.input#item1-1[value="s"],
.input#item1-1[value="S"] 
  

Ma questo non funzionerà. Il selettore di attributi selezionerà l'elemento in base a ciò che è effettivamente all'interno dell'HTML e non considera le modifiche in tempo reale. Quindi ho dovuto ricorrere al :valid approccio di pseudo-classe descritto sopra, e di conseguenza (e fastidiosamente) esporre le risposte nello stesso HTML.

Evidenziando gli indizi al passaggio del mouse

Tutti gli indizi orizzontali (trasversali) sono racchiusi in un file div, così come lo sono gli indizi verticali (in basso). Questi avvolgimento div gli elementi sono fratelli di input elementi nella griglia delle parole crociate. Ciò è dimostrato nella struttura HTML sopra elencata in un blocco di codice precedente. Ciò semplifica la selezione degli indizi corretti a seconda di quale elemento di input viene messo a fuoco / al passaggio del mouse.

Cruciverba al passaggio del mouse

Per questo, ciascuno input elemento ha bisogno :active, :focus, e :hover stili per evidenziare l'indizio pertinente applicando un colore di sfondo quando l'utente interagisce con un file input elemento.

#item1-1:active ~ .crossword-clues .crossword-clues__list-item--across-1,
#item1-1:focus ~ .crossword-clues .crossword-clues__list-item--across-1,
#item1-1:hover ~ .crossword-clues .crossword-clues__list-item--across-1 
  background: #ffff74;

Numerare gli indizi

I numeri per gli indizi sono posizionati utilizzando un pattern CSS Grid. Ecco un esempio dell'HTML, abbreviato:

<div class="crossword-board crossword-board--labels">
  <span id="label-1" class="crossword-board__item-label crossword-board__item-label--1">
  <span class="crossword-board__item-label-text">1</span></span>
  <span id="label-2" class="crossword-board__item-label crossword-board__item-label--2">
  <span class="crossword-board__item-label-text">2</span></span>

  

</div>

Quindi il CSS ha un aspetto simile a questo:

.crossword-board__item-label--1 
  grid-column: 1/1;


.crossword-board__item-label--2 
  grid-column: 4/4;


Ogni numero viene posizionato nella posizione iniziale del relativo gruppo di elementi di input (o parola). Il numero viene quindi creato per essere la larghezza e l'altezza di 1 quadrato della griglia in modo che occupi il minor spazio possibile all'interno della griglia. Potrebbe occupare ancora meno spazio implementando CSS Grid in modo diverso qui, ma ho scelto di farlo in questo modo.

La casella di controllo "Check for Valid Squares"

Nella parte superiore del cruciverba, noterai una casella di controllo denominata "Verifica la presenza di quadrati validi". Ciò consente all'utente di verificare se determinate lettere sono corrette, anche se una determinata parola è sbagliata.

Cruciverba quadrati validi evidenziati

Creare questo è piuttosto bello in quanto è una regola CSS che fa in modo che tutti i quadrati validi vengano evidenziati. Sta usando la casella di controllo hack per selezionare tutti gli elementi di input validi che si trovano dopo la casella di controllo selezionata nel DOM.

Ecco il codice:

#checkvaliditems:checked ~ .crossword-board-container .crossword-board__item:valid 
  background: #9aff67;

Conclusione

Questo copre tutte le principali tecniche utilizzate nella demo. Come esercizio, questo mostra fino a che punto sono arrivati ​​i CSS negli ultimi anni. Ci sono molte funzionalità con cui possiamo essere creativi. Io per primo non vedo l'ora di provare a spingere altre nuove funzionalità al limite!

Se vuoi scherzare con il CSS di questo articolo, ho inserito tutti gli esempi di codice in una collezione CodePen. Il pieno funzionamento Il cruciverba CSS può essere trovato qui.

Potresti anche essere interessato a