Horizontalus centravimas
Šitas įrašas yra visai ne apie tai, kas būtų jeigu Sabonis žaistų krepšinį gulėdamas ant grindų (tiesa, esu įsitikinęs, kad jis tai darytų puikiai). Ir tikiuosi iš pirmojo sakinio supratote, kad nesusipainiojau ir (beveik) neketinu kartotis vertikalaus centravimo tema.
Dažniausiai norint nežinomo pločio elementą išcentruoti horizontaliai kitame elemente problemų nekyla – užtenka tiesiog paprasto text-align:center;
ar kiek sudėtingesnio display:block; margin-left: auto; margin-right: auto;
. Šie abu variantai netinka tuo atveju, kai vidinis elementas yra platesnis negu išorinis. Jeigu tas vidinis elementas yra paveiksliukas, jį galima perkelti į foną ir uždėti background-position: 50% 50%;
, tačiau kartais tiesiog nėra techninės galimybės nenaudoti <img>
, o galbūt kai kam kiltų noro ir žaisti su kitokiais elementais.
Alternatyvus variantas, be abejo, yra naudoti tam JavaScript, tačiau pritaikom Auksinę Gero Tinklo Taisyklę: HTML naudojamas aprašymui (mark-up), CSS atvaizdavimui (presentation), o JS elgsenai/veikimui (behavior)- centravimas yra atvaizdavimas, taigi JS netinka.
Praktinė užduotis
Turime didelę duomenų bazę, kurioje sukauptas kalnas sumažintų paveiksliukų (thumbnails). Dauguma jų yra 150px pločio, tačiau pasitaiko ir kitokių. Kaip juos visus “apkarpyti” parodant tik vidurinę dalį 100px pločio rėmelyje? Galima naudotis tik CSS ir <img>
dėl accessibility.
Sprendimas: kaip centruoti nežinomo pločio vidinį elementą
Nustok man kvaršinti galvą ir duok pilną sprendimą.
Jeigu turime fiksuoto pločio išorinį rėmelį, ir visiškai nežinomo pločio (platesnį arba siauresnį) vidinį elementą, tenka šiek tiek pavargti. Matematika atrodytų paprasta – kažkokiu būdu pastumti vidinį elementą per pusę išorinio elemento pločio, ir patraukti atgal per pusę vidinio elemento pločio, taip sulygiuojant jų centrines linijas. Lengviau pasakyti, negu padaryti…
Pirmas žingsnis – pastumiam į šoną
Išoriniam elementui .frame
uždedame fiksuotą plotį ir overflow: hidden;
, kad jokie išsiplėtę vidiniai elementai jo nepakeistų. Tada sukuriame pirmą vidinį rėmelį perkėlimui – .shiftLeft
, kuris paprasčiausiai turi papildomą paraštę, kurios plotis yra pusė išorinio rėmelio. Sprendime naudoju pikselius, bet manau, kad turėtų veikti ir procentai.
Antras žingsnis – patraukiam atgal
Patraukti vidinį elementą per pusę jo paties pločio atgal yra kiek sudėtingiau – panaudoti neigiamos paraštės negalima, nes paraščių procentiniai pločiai, pagal standartus, yra skaičiuojami nuo tėvinio elemento pločio. Šią problemėlę galima išspręsti, jeigu vidinis elementas yra “plaukiojantis”. Kadangi kai kurios naršyklės (ghkhmz) tai palaiko ne visai tiksliai – tenka naudoti du elementus – vienam jų (.floatToFix
) uždėti float
ir užfiksuoti plotį, o su kitu (.unshift
) traukti atgal. Į .unshift
vidų jau galime įdėti neapibrėžto pločio paveiksliuką – nerekomenduočiau jam pačiam taikyti patraukimo atgal klasės…
Trečias žingsnis – sprendžiam problemas
Gana dažnai dėl klaidos kode (double margin bug) tam tikra naršyklė (ghkhmz) pritaiko dvigubą plotį plaukiančių elementų paraštėms – tai galima spręsti su display: inline;
, tačiau šiuo atveju vistik tenka traukimo veiksmą pakeisti iš paraščių į santykinį pozicionavimą ir panaudoti tiesiog neigiamą left: -50%;
. Su tuo santykiniu patraukimu atsiranda kita problema (toje pačioje, tam tikroje, naršyklėje (ghkhmz)) – vidinis elementas išlipa į viršų ir nebepaiso overflow
. Tai galima išspręsti nustatant position: relative;
ir visiems tėviniams elementams.
Galutinis sprendimas
Kažkodėl pažvelgus į jo kodą, atrodo, kad viskas taip elementaru, tačiau teko gerokai paeksperimentuoti, kol pasiekiau veikiantį variantą. Kas keisčiausia, vos vos jį pakeitus viskas sugriūna! Panašu, kad galutinė versija veikia teisingai su:
- Internet Explorer 6
- Internet Explorer 7
- Firefox 2
- Opera 9.26
- Safari 3.1
Su Safari, tiesa, kartais atsiranda gana keistas perpiešimo efektas – dalis vidinio elemento pradingsta, tačiau pakeitus lango dydį viskas sugrįžta į vietas. Jeigu kas galite patikrinti su kitomis naršyklėmis – būtų malonu išgirsti rezultatus, o šiaip jeigu prireiks šio sprendimo – naudokit į sveikatą ir neminėkit piktuoju, jeigu kas nors neveiks. Bandysiu pritaikyti ir vertikalų centravimą, tačiau bijau, kad aukštesniems elementams jis neveiks… Todėl eksperimento rezultatuose yra variantas, kuris pakeičia vidinio paveikslėlio aukštį – darant tai naršyklėje vaizdas kiek sugenda, tačiau galbūt geriau negu nieko?
5 Responses to “Horizontalus centravimas”
Komentarų RSSeeem… ką?
tu kažkoks kosmosas :(
p.s. nu bet toks geras kosmosas :)
Visai čia ne kosmosas, o vienas retesnių tikrai daug vertės turinčių IT patarimų LT blogosferoje ;)
QQ, o tu mano bendradarbis :P
[...] knygų sąrašas (pradedant storiausia), istorinė makalynė žemėse šiauriau Lietuvos, taisyklingo horizontalaus centravimo svetainėje vadovas, padėkite surasti Asfaltą – katinėlį, intriguojančio „vėjo“ recenzija ir greiti [...]
[...] idėjos tiesiog veiktų (su visomis naršyklėmis) – tiek hasFocus/activeElement, tiek horizontalaus centravimo sprendimai gimė būtent iš [...]