Cum ati face contrastul automat în CSS?

Tot stau de câteva ore bune la următoarea chestiuță:

Nu pot arăta mai mult din cauză de NDA, dar:

  • linia verticală este un timeline pe toată înălțimea paginii;
  • atât linia cât și textul poate trece peste imagini dar pot exista și fără imagini;
  • imaginile pot fi atât deschise la culoare (caz în care linia și textul trebuie să rămână negre) cât și închise la culoare (caz în care linia și textul trebuiesc să fie albe);
  • designul este fluid, ceea ce înseamnă că la redimensionarea paginii, dimensiunea imaginilor este ajustată proporțional.

Ce nu merge? În CSS aveam ceva speranțe la mix-blend-mode, dar pe lângă suportul în browsere scăzut, nici nu face ce am nevoie…

Cum m-am gândit? Cu ceva JS care duplică elementele problematice, le poziționează absolut etc. Mă îngrijorează performanța, pentru că sunt destul de multe astfel de elmente (este un timeline întins pe vreo 15-20 ani, cu câte 2-3 intrări/an)

Alte idei? Sugestii?

Nu prea am inteles eu exact cum e situatia, dar poti lua imaginea, o copiezi intr-un canvas invizibil, iei pixelii intre coordonatele x,y si z, w aplicand un algoritm pentru a afla o culoare mediana. Cu textul momentan nu am nici o idee, dar teoretic poti lua pixelii dintr-o zona, in functie de latimea textului, font size, font family. Cred ca HTML5 canvas is your best friend in situatia asta.

1 Like

Ai putea sa-ti incerci norocul folsind ceva de genul, iar .bara sa aiba width-ul modificat cu JS. Nota: Nu stiu daca merge content la imagine…

img{
  content:"<b class=\"bara\"></b>";
}
.bara {
  float:right;
  border:none;
  border-left:1px white strong;
  height:100%;
  width: 0%;
}

Edit: Nu merge img{content:"stuff"}. Dar poti avea acea imagine intr-un <i>, <b>, sau <span> si ar trebui sa mearga.
Problema ramane, totusi, sa calculezi cat este de la linia neagra pana la marginea din stanga sau (either or) din dreapta a imagini. Daca este ceva constant, este mai usor de rezolvat.

Nu cred că există o soluție simplă CSS la această problemă, însă cu puțin javascript cred că o poți rezolva cât de cât.

Să zicem că timelineul are o structură de genul:

`



Test 1

Test 2

`

După ce se încarcă pagina, atașezi pentru fiecare imagine câte un div în #timeline și îl memorezi într-o prorietate la imagine. Stilizezi divurile să fie exact ca și linia de timeline, dar lași top și height nesetat.

La onresize verifici dacă vreo imagine intersectează linia de timeline și dacă da, setezi top și height liniei imaginii respective. Apoi verifici fiecare “.event” dacă se intersectează cu vreo imagine și ii setezi clasa white / black.

Ca să determini ce culoare să setezi, alb sau negru, la scris și la linie, poți la început să aproximezi rând pe rând fiecare imagine, cu canvas, și să memorezi rezultatul, dacă este închisă sau deschisă.

Cred că este o soluție ok, care se mișcă bine, dacă scrii codul optimizat bine.

Poate dacă am avea mai multe detalii am avea soluții mai bune :slight_smile: dar e interesantă problema

Cred ca provocarea e cum decizi daca linia si textul sunt negre sau albe.
Imaginea poate fi orice imagine (imaginea este uploadata de user)?
In acest caz cred ca nici mix-blend-mode nu ajuta, caci din ce inteleg linia, cercul si textul trebuie sa fie fie albe, fie negre in intregime, dar din ce stiu mix-blend-mode lucreaza la nivel de pixel, poate ma insel?

Cred ca ce iti trebuie este calcularea culorii dominante dintr-o imagine:
http://benhowdle.im/Adaptive-Backgrounds/
http://thesassway.com/intermediate/dynamically-change-text-color-based-on-its-background-with-sass (vezi si comment-urile)
http://codepen.io/aamirafridi/pen/gnxuf (desi culoarea textului are un efect de transparenta, nu este doar alb sau negru cum ai tu nevoie)

Legat de performanta, daca timeline-ul este de 20 ani x 3 intrari/an = 60 imagini.
Daca vrei sa faci in clientside trebuie sa vezi cat timp ia algoritmului de extragere al culorii dominante pentru o imagine. In loc sa aplici algoritmul la toate imaginile deodata, ai putea sa o aplici numai la imaginile care sunt in sau langa viewport (similar cu modul in care functioneaza lazy loading la imagini).
O alta optiune e sa calculezi culoarea dominanta pentru fiecare imagine direct pe backend, atunci cand imaginea este uploadata de user, astfel incat pe client deja stii daca trebuie folosit alb sau negru pentru linie, cerc si text.

O alta problema ar fi legata de desenarea cu o anumita culoare a liniei, cercului si textului doar pe imagine, in timp ce intre imagini este o alta culoare.
Avand in vedere ca imaginile iau oricum timp sa se incarce si userul poate face scroll in jos, frumos e ca linia, cercul si textul sa fie deja acolo (desenate cu negru daca fundalul paginii e alb) si apoi dupa ce imaginea se incarca, linia, cercul si textul de deasupra se schimba la culoare in functie de culoarea dominanta a imaginii.

O alta rezolvare mult mai simplista ar fi prin schimbarea designului, daca clientul e de acord: linia, cercul si textul sa fie umplte cu culoarea negru si aiba un edge alb. In felul asta merge peste orice imagine, nu ai nevoie sa stii culoarea dominanta. Dar nu stiu cat de bine arata, trebuie incercat in Photoshop.

Oricum ar fi, as incepe cu layoutul imaginilor, al liniei, cercului si textului care trebuie sa fie redimensionate dupa pagina. Apoi m-as gandi la culoarea in functie de imagine.

Hope this helps…

1 Like

Nu e o provocare prea mare, se face pe server chestia asta.

Exact.


Problema constă în faptul că și textul poate fi parțial pe o imagine, caz în care trebuie să asigur și acolo un… ceva.

Cel mai probabil asta va fi soluția :slight_smile:

Fara canvas si procesare per pixel nu prea vad cum, dar nu cred ca se merita osteneala, mai ales daca linia se mai si plimba eventual peste imagine (cand scrollezi timeline-ul sau mai stiu eu ce).

Incearca sa vezi cum arata o line #333 cu o linie #ccc plasata la un pixel in dreapta primei (ca un fel de shadow). Asa ai sanse sa se vada “ceva” indiferent cum e imaginea. Si tine degetele incrucisate sa arate decent si sa-i convina clientului :slight_smile:

2 Likes

sau shadow cu css, eu nu stiu ce anume e linia aia, div, imagine mica, etc

faci un div, ori de 2-3px cat are dunga pus pe centru, ori % din imagine pe width aliniat la stanga sau center cu un border in dreapta, depinde cum se face resize-ul la schimbarea rezolutiei. Zona alba de peste si sub imagine vor fi alte divuri.
Zona din dreapta, alt div, cu z-indez pe el. Textul il printezi de doua ori, odata peste partea din dreapta,si inca odata peste partea din stanga. Folosesti z-index si pui partea cu poza deasupra. N-ar trebui sa ai nevoie de js. O solutie simpla ar fi ca atunci cand userul uploadeaza imaginea sa aleaga si culoarea liniei. Ca o paranteza, imi plac designeri astia, au viziune si cateodata iese ceva interesant. Dar mai sunt si momente dinastea.

1 Like

Pentru că era criză de timp, s-a mers pe următoarea soluție:

  • s-a ajustat design-ul , astfel încât anul să fie într-o bulină plină;
  • linia verticală are position: fixed și z-index mic, doar pentru a fi vizibilă în momentele mai speciale;
  • fiecare secțiune are câte o altă linie verticală, poziționată absolut, tot pe centru, astfel încât este poziționată fix peste linia „principală” (menționată mai sus);
  • culoarea fiecărei linii individuale este setată pe baza unui checkbox (is_bright_bg), din admin (și a bulinei).

Merge ok…ish, cu condiția să se folosească fix o anumită dimensiune pentru imagini. La următoarea iterație voi adăuga ceva mai multă flexiblitate :slight_smile: