Podczas kodowania nowego designu wpadłem w pewną pułapkę — umieszczałem przypisy boczne w kodzie po lub przed danym akapitem. W efekcie, czytając artykuł w czytniku RSS można było poczuć niemałą dezorientację, kiedy ni stąd ni zowąd pojawiała się niespójna logicznie treść. Postanowiłem rozwiązać ten problem, przy okazji publikując i omawiając zastosowane przeze mnie rozwiązanie.
Naszym celem jest stworzenie przypisów dolnych tak, aby wyglądały jako boczne, zupełnie jak na tym blogu. Jeśli w jakimś akapicie znajdzie się odnośnik do przypisu, jego treść powinnna pojawić się z prawej strony akapitu (tagu <p />). Zacznijmy od semantycznego szablonu:
<div class="article">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus massa. Fusce sed erat. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Suspendisse auctor neque id purus. Ut dignissim felis et velit suscipit fringilla. Aenean et est et lacus interdum rutrum.<a href="#przypis-1" class="hint"><sup>1</sup></a> Nam iaculis ipsum vel neque blandit placerat. Cras dui elit, varius at, gravida a, consectetur ut, elit. Donec turpis. Fusce quis sapien ac nisl lobortis eleifend. Morbi posuere, massa vel fermentum commodo, arcu quam fermentum turpis, vel tincidunt ante odio at arcu. Sed vitae purus.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus massa. Fusce sed erat. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Suspendisse auctor neque id purus. Ut dignissim felis et velit suscipit fringilla. Aenean et est et lacus interdum rutrum. Nam iaculis ipsum vel neque blandit placerat. Cras dui elit, varius at, gravida a, consectetur ut, elit. Donec turpis. Fusce quis sapien ac nisl<a href="#przypis-2" class="hint"><sup>2</sup></a>lobortis eleifend. Morbi posuere, massa vel fermentum commodo, arcu quam fermentum turpis, vel tincidunt ante odio at arcu. Sed vitae purus.</p>
<hr />
<ol id="notes">
<li id="przypis-1">First note</li>
<li id="przypis-2">Second note</li>
</ol>
</div>
Jak widać, kontenerem dla artykułu jest .article, odnośnikami do przypisów są linki .hint. Domyślne przypisy dolne tworzy lista #notes.
Pora na trochę podstawowych CSSów. Wypozycjonujmy treść, nadajmy odpowiednie typy fontów i tak dalej:
* {
padding: 0;
margin: 0;
}
a {
text-decoration:none;
color: #7EBB1F;
font-weight: bold;
}
a:hover {
background-color: #7EBB1F;
color: #fff;
}
.article {
width: 960px;
margin: auto;
font: normal 14px 'Lucida Sans Unicode', Arial, Helvetica, sans-serif;
}
.article p {
margin-bottom: 20px;
line-height: 20px;
width: 680px;
}
Generalnie, cel jest następujący – jeśli mamy włączony JavaScript usuwamy listę numerowaną <ol#notes />, a jej elementy zmieniamy na <p /> i umieszczamy pomiędzy stosownymi akapitami artykułu. To teoretyczny opis. W praktyce będzie to zrobione nieco inaczej.
Poszukamy akapitów, które linkują do określonych przypisów. Jeśli dany akapit zawiera link .hint to dodajemy zaraz po nim stosowny przypis. Treść przypisu pobierzemy na podstawie identyfikatora, który znajduje się po hashu (#) w linku-odnośniku.
Najpierw jednak zajmijmy się sytuacją, kiedy mamy wyłączony JavaScript:
.article hr {
border: none;
border-top: 1px solid #7EBB1F;
width: 680px;
float: left;
margin-bottom: 10px;
}
.article #notes {
clear: left;
}
#notes li {
font-size: 11px;
width: 680px;
margin-bottom: 3px;
line-height: 15px;
font-style: italic;
}
Powyższym ostylowaliśmy przypisy dolne – w końcu jeśli JavaScript będzie wyłączony, to będzie trzeba jakoś je zaprezentować. Warto sprawdzić efekt.
Fajnie jednak byłoby, gdyby jakiś aktywny przypis (tzn. ten, w który kliknęliśmy) został nieco wyróżniony. Zrobić możemy to dzięki selektorowi :target:
#notes li:target {
font-weight: bold;
}
Oznacza to, że jeśli w linku pojawi się identyfikator jakiegoś tagu <li /> np. przypis1.html#przypis-2 to treść tego tagu (tutaj: < li id=”przypis-2″ />) zostanie wyboldowana. Wynika na to, że załatwiliśmy problem wyłączonego JavaScriptu.
Zajmijmy się teraz odpowiednimi skryptami, które przeniosą elementy z listy #notes pod stosowne akapity. Skorzystamy w tym celu z jQuery.
Najpierw należy poszukać wszystkich linków .hint w obrębie artykułu .article:
$().ready(function() {
$('.article .hint').each(function(i, element) {
Dzięki funkcji each przeiterujemy się przez wszystkie znalezione odnośniki do przypisów. Pierwsze, co powinniśmy zrobić, to znaleźć akapit, który jest rodzicem danego linku:
$().ready(function() {
$('.article .hint').each(function(i, element) {
var parent = $(element).parent('p');
Następnie pobieramy adres linku, by uzyskać identyfikator przypisu, do którego się on odnosi:
$().ready(function() {
$('.article .hint').each(function(i, element) {
var parent = $(element).parent('p');
var id = $(element).attr('href');
Tym sposobem pod zmienną id będą następujące wartości:
- #przypis-1
- #przypis-2
- itd.
Pora pobrać treść przypisu na podstawie jego ID i uformować nowy akapit z przypisem:
$().ready(function() {
$('.article .hint').each(function(i, element) {
var parent = $(element).parent('p');
var id = $(element).attr('href');
var note = $(id).html();
var newNote = $('<p class="note"><sup id="'+id.replace(/#/g, '')+'">'+(i+1)+'</sup>'+note+'</p>');
Szczególnie istotna jest tutaj 8. linijka:
var newNote = $('<p class="note"><sup id="'+id+'">'+(i+1)+'</sup>'+note+'</p>');
Otóż dzięki niej tworzymy nowy tag drzewa DOM jakim jest <p />. Oczywiście ubieramy go w stosowne wdzianko - nadajmy class="note" - tak, by potem można było ostylować przypis boczny. W nowym przypisie umieszczamy również indeks w <sup />, korzystając ze zmiennej i z pętli each - jej wartość zaczyna się standardowo od zera, więc należy dodać jeden, by otrzymać zwykłe odliczanie od 1. Znacznik sup musi mieć dobry identyfikator bez hasha na początku. Wyrzucamy więc "#" przez id.replace(/#/g, '').
Trzeba jeszcze zająć się pozycjonowaniem przypisu tak, by był wertykalnie nieco bliżej jego odnośnika .hint. Spróbujemy ustawić tak dobrany, ujemny margin-top, by nie było zbytnich przerw pomiędzy wspomnianym linkiem i akapitem z przypisem.
$().ready(function() {
$('.article .hint').each(function(i, element) {
var parent = $(element).parent('p');
var id = $(element).attr('href');
var note = $(id).html();
var newNote = $('<p class="note"><sup id="'+id.replace(/#/g, '')+'">'+(i+1)+</sup>'+note+'</p>');
newNote.css('margin-top', (parseInt($(parent).css('margin-bottom')) + ($(parent).height() + $(parent).offset().top) - $(element).offset().top) * -1);
Stosowny margines górny ustawiamy na podstawie prostego wyliczenia. Sumujemy wysokość i odległość od początku strony całego akapitu, a następnie od tej sumy odejmujemy odległość linku od początku strony. Odległość od początku strony możemy pobrać przez jQuery'owe offset().top, a wysokość przez height(). Do wszystkiego dodajemy jeszcze margines dolny akapitu, w którym mieści się link. Wszystko mnożymy razy minus jeden, by uzyskać ujemny margines dla naszego przypisu. Oto rysunek poglądowy, jak wyliczamy margines:

Pora dodać nowy przypis pod stosowny akapit i zakończyć pętlę each:
$().ready(function() {
$('.article .hint').each(function(i, element) {
var parent = $(element).parent('p');
var id = $(element).attr('href');
var note = $(id).html();
var newNote = $('<p class="note"><sup id="'+id.replace(/#/g, '')+'">'+(i+1)+'</sup>'+note+'</p>');
newNote.css('margin-top', (parseInt($(parent).css('margin-bottom')) + ($(parent).height() + $(parent).offset().top) - $(element).offset().top) * -1);
newNote.insertAfter(parent);
});
Na koniec musimy jeszcze usunąć przypisy dolne, które nie są już nam potrzebne:
$().ready(function() {
$('.article .hint').each(function(i, element) {
var parent = $(element).parent('p');
var id = $(element).attr('href');
var note = $(id).html();
var newNote = $('<p class="note"><sup id="'+id.replace(/#/g, '')+'">'+(i+1)+</sup>'+note+'</p>');
newNote.css('margin-top', (parseInt($(parent).css('margin-bottom')) + ($(parent).height() + $(parent).offset().top) - $(element).offset().top) * -1);
newNote.insertAfter(parent);
});
$('#notes').prev('hr').remove();
$('#notes').remove();
});
Wynik naszej zabawy nie wygląda jednak zbyt atrakcyjnie.
Pora dodać stosowne style dla .note:
.article .note {
float: right;
background-color: #FBF1AB;
border: 1px solid #ECD42B;
width: 162px;
padding: 4px;
overflow: hidden;
font-size: 12px;
}
.article .note sup {
float:left;
font-size:20px;
vertical-align: bottom;
margin-right: 5px;
text-align: center;
width: 30px;
}
.article .note sup:target {
background: #FBEA71;
}
Jest całkiem nieźle!
Można by co prawda zwiększyć widoczność odnośników do przypisów:
.article .hint {
margin-right: 10px;
}
.article .hint sup {
font-size: 14px;
}
Zastosowane tutaj rozwiązanie ma w zasadzie tylko jedną wadę - nie należy nadużywać przypisów w jednym akapicie, ponieważ mogą one na siebie nachodzić, tworząc dość nieprzyjemny efekt. Oczywiście możemy nie stosować pozycjonowania względem odnośnika, usuwając linijkę odpowiedzialną za ustawianie górnego marginesu. Wtedy możemy stawiać przypisy gdziekolwiek i w jakiej ilości chcemy.

Komentarze
Hmm, muszę sobie ten artykuł przeanalizować, bo średnio rozumiem fragment o pozycjonowaniu. Efekt – robi wrażenie :)
Świetne rozwiązanie :-) Tutorial dobry, choć ja akurat wykorzystałbym funkcję „wrap()” znaną z jQuery, a nie pisał dość brzydki kawałek kodu sklejający tag z kilku stringów ;-)
Pozdrawiam
Niezły efekt, pewnie się przyda przy niektórych projektach :)
Fajnie :)
ps
po:
Na koniec musimy jeszcze usunąć przypisy dolne, które nie są już nam potrzebne:
ominoles jeden ‘ w:
# var newNote = $(”+(i+1)+’+note+”);
przed
moim zdaniem użyto armaty na muchę, dodatkowo strzelając do niej zamiast ją oswoić..
Przecież przypisy w książkach wyglądają jak wyglądają, bo się ich nie dało zrobić lepiej – nikt mi nie powie że są wygodne.
w htmlu używa się po prostu atrybutu title i cała treść przypisu jest wszyta w treść – nie trzeba uciekać wzrokiem nie wiadomo gdzie(wracać przewijać itd itd).
Używanie JS i CSS tylko po to żeby zasymulować wady książek papierowych jest bez sensu. Efekt przyjemny dla oka, ale czy wygodny?
Bardzo to czasochłonne. Potrzebuję szybko wstawić dolny przypis a tu taka zabawa.