chevron-left chevron-right

Piotr Nalepa Frontend, architektura i AI

[CSS][jQuery] Efektowne menu z kwadratami

Ta wersja
blog.piotrnalepa.pl/2011/03/28/cssjquery-efektowne-menu-z-kwadratami
Opublikowano
Autor
, Staff Software Engineer
Kategorie
CSS, JavaScript
Uwagi
Napisz do mnie · Napisz na X

Ten wpis ma 15 lat. Od tego czasu przeglądarki i narzędzia mogły się zmienić, więc zanim użyjesz kodu, sprawdź go z aktualną dokumentacją.

W dzisiejszym artykule, przedstawię Ci sposób na stworzenie efektownego menu bazującego na kwadratach. Bardzo często podobne menu można spotkać na stronach zbudowanych w oparciu o Flash. Ten poradnik przedstawi Ci sposób na zbudowanie tego samego efektu za pomocą CSS i jQuery.

Sekcja 1Struktura HTML

Na początek należy przygotować sobie odpowiednią strukturę pliku HTML, która będzie się opierała na jednym głównym kontenerze z wieloma mniejszymi kontenerami (divami) w środku. Niektóre z nich będą zawierały linki i treści, a niektóre będą zawierały predefiniowane pozycje obrazka, dzięki czemu uzyskamy efekt mozaiki z jednego obrazka. Wszystkie elementy są pozycjonowane absolutnie. Niektóre z elementów zawierają tzw. style wewnętrzne, nie zdefiniowane w sekcji stylów CSS w HEAD. Ma to na celu ułatwienie pozycjonowania elementów mozaiki.
Przykład 1HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<div id="boxy" class="boxy">
	<div class="boxlink bg1" style="top: 0px;left: 0px;">
		<a href="">O mnie</a>
		<div class="boxcontent">
			<p><img src="ja.jpg" alt="" style="float: left; margin: 0 10px 10px 0;" />Lorem ipsum dolor sit amet, consectetur adipisicing elit,
				sed do eiusmod tempor incididunt ut labore et dolore magna
				aliqua. Ut enim ad minim veniam, quis nostrud exercitation
				ullamco laboris nisi ut aliquip ex ea commodo consequat.
			</p>
		</div>
	</div>
	<div class="bg5" style="background-position: -90px 0;top: 0px;left: 95px;"></div>
	<div class="bg5" style="background-position: -180px 0;top: 0px;left: 190px;"></div>
	<div class="bg5" style="background-position: -270px 0;top: 0px;left: 285px;"></div>
	<div class="bg5" style="background-position: 0 -90px;top: 95px;left: 0px;"></div>
	<div class="boxlink bg2" style="top: 95px;left: 95px;">
		<a href="">Portfolio</a>
		<div class="boxcontent">
			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
				sed do eiusmod tempor incididunt ut labore et dolore magna
				aliqua. Ut enim ad minim veniam, quis nostrud exercitation
				ullamco laboris nisi ut aliquip ex ea commodo consequat.
			</p>
		</div>
	</div>
	<div class="bg5" style="background-position: -180px -90px;top: 95px;left: 190px;"></div>
	<div class="bg5" style="background-position: -270px -90px;top: 95px;left: 285px;"></div>
	<div class="bg5" style="background-position: 0 -180px;top: 190px;left: 0px;"></div>
	<div class="bg5" style="background-position: -90px -180px;top: 190px;left: 95px;"></div>
	<div class="boxlink bg3" style="top: 190px;left: 190px;">
		<a href="">Projekty</a>
		<div class="boxcontent">
			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
				sed do eiusmod tempor incididunt ut labore et dolore magna
				aliqua. Ut enim ad minim veniam, quis nostrud exercitation
				ullamco laboris nisi ut aliquip ex ea commodo consequat.
			</p>
		</div>
	</div>
	<div class="bg5" style="background-position: -270px -180px;top: 190px;left: 285px;"></div>
	<div class="bg5" style="background-position: 0 -270px;top: 285px;left: 0px;"></div>
	<div class="bg5" style="background-position: -90px -270px;top: 285px;left: 95px;"></div>
	<div class="bg5" style="background-position: -180px -270px;top: 285px;left: 190px;"></div>
	<div class="boxlink bg4" style="top: 285px;left: 285px;">
		<a href="">Kontakt</a>
		<div class="boxcontent">
			<form>
				<fieldset>
					<ul>
						<li><label>Email: </label><input type="text"/></li>
						<li><label>Treść: </label><textarea></textarea></li>
						<li><input type="submit" value="Wyślij" />
					</ul>
				</fieldset>
			</form>
		</div>
	</div>
</div>

Sekcja 2Style CSS

Teraz czas na style CSS, które określą wstępny wygląd naszego menu:
Przykład 2CSS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
.boxy {
    width: 350px;
    height: 350px;
    margin: 200px auto;
    position: relative;
}
.boxy > div {
    position: absolute;
    width: 90px;
    height: 90px;
    text-align: center;
    border: 2px solid #a3a3a3;
    overflow: hidden;
    background-color: #f7f7f7;
    -moz-box-shadow: 0px 0px 3px #555;
    -webkit-box-shadow: 0px 0px 3px #555;
    box-shadow: 0px 0px 3px #555;
    background-position: center center;
    z-index: 999;
}
.boxy div a {
    text-transform: uppercase;
    font-size:  16px;
    font-weight: bold;
    letter-spacing: -1px;
    display: block;
    line-height: 90px;
    text-decoration: none;
    color: #fff;
    background: #91EF4A url(bgItem.jpg) repeat-x top left;
    outline: none;
    text-shadow: 1px 1px 1px #888;
    -moz-box-shadow: 1px 1px 3px #777;
    -webkit-box-shadow: 1px 1px 3px #777;
    box-shadow: 1px 1px 3px #777;
}
.boxy div.boxcontent {
    width: 334px;
    height: 246px;
    text-align: left;
    padding: 10px;
    font-size: 16px;
    background-color: #000;
    border: 2px solid #fff;
    margin: 10px 0px 0px 10px;
    text-shadow: 1px 1px 1px #000;
    -moz-box-shadow: 1px 1px 3px #777;
    -webkit-box-shadow: 1px 1px 3px #777;
    box-shadow: 1px 1px 3px #777;
    opacity: 0.8;
    display: none;
    color: #fff;
}
.bg1, .bg2, .bg3, .bg4 { background-repeat: no-repeat; }
.bg1 { background-image: url(bg1.jpg); }
.bg2 { background-image: url(bg2.jpg); }
.bg3 { background-image: url(bg3.jpg); }
.bg4 { background-image: url(bg4.jpg); }
.bg5 { background-image: url(bg5.jpg); }
Nasz główny kontener: .boxy, jest wycentrowany na stronie i pozycjonowany relatywnie. Kontenery wewnątrz kontenera .boxy zawierają jednolity styl. Są pozycjonowane absolutnie i mają dodany przyjemny w odbiorze efekt cienia. Treść wybranych kontenerów ujawnia się w momencie kliknięcia w link, dlatego wstępnie kontenery z treścią są ukryte.

Sekcja 3JavaScript

Na początek, należy załadować bibliotekę jQuery oraz jQuery.UI. Mając je załadowane możemy przejść do tworzenia docelowego efektu. Aby uzyskać efekt "swobodnego lotu" musimy zapisać początkowe pozycje każdego z kontenerów, dzięki czemu będziemy mogli przywrócić ich pozycje za pomocą kliknięcia w element menu. Kiedy klikniemy w element menu, następuje losowa animacja pozycji kontenerów a kliknięty element rozwija się do maksymalnych zdefiniowanych rozmiarów głównego kontenera. Ponadto, animuje się treść klikniętego kontenera. Jeśli klikniemy nagłówek rozwiniętego kontenera, to następuje powrót do domyślnego widoku menu.
Przykład 3JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
$(function() {
	/* obiekt zapisujący pozycje konenterów */
	var divinfo = {"initial": []};
	/* indeks wybranego/klikniętego kontenera */
	var current = -1;
 
	/* zapisujemy index, pozycję top, pozycję left każdego kontenera */
	$('#boxy > div').each(function(){
		var $this = $(this);
		var initial = {
					'index' : $this.index(),
					'top'     : $this.css('top'),
					'left'     : $this.css('left')
		};
		divinfo.initial.push(initial);
	});
 
	/* wywoływanie zdarzenia po kliknięciu w kontener */
	$('#boxy a').bind('click',function(e){
			var $this         = $(this);
			var $currentBox    = $this.parent();
			/* ustaw z-index mniejszy niż reszty kontenerów,
			aby zobaczyć animację innych kontenerów na górze*/
			$currentBox.css('z-index','1');
 
			/* jeśli klikniemy na rozwinięty kontener: */
			if(current == $currentBox.index()){
				/* przywróć widok domyślny (zmniejsz szerokość, wysokość
				i wyzeruj pozycje top i left)
				domyślne wartości są zapisane w obiekcie divinfo*/
				$currentBox.stop().animate({
						'top'  : divinfo.initial[$currentBox.index()].top,
						'left' : divinfo.initial[$currentBox.index()].left,
						'width'  : '90px',
						'height' : '90px'
				},800,'easeOutBack').find('.boxcontent').fadeOut();
 
				$('#boxy > div').not($currentBox).each(function(){
					var $ele         = $(this);
					var elemTop     = divinfo.initial[$ele.index()].top;
					var elemLeft     = divinfo.initial[$ele.index()].left;
					$ele.stop().show().animate({
						'top'         : elemTop,
						'left'        : elemLeft,
						'opacity'    : 1
					},800);
				});
				current = -1;
			}
			/* jeśli klikniemy na mały kontener : */
			else{
				/* losowo animuj inne konentenery. */
				$('#boxy > div').not($currentBox).each(function(){
					var $ele = $(this);
					$ele.stop().animate({
						'top' : (Math.floor(Math.random()*601) - 150) +'px',
						'left': (Math.floor(Math.random()*601) - 150) +'px',
						'opacity':0
					},800,function(){
						$(this).hide();
					});
				});
 
				/* powiększ kliknięty, a także animuj kontener z treścią */
				var newwidth     = 379;
				var newheight     = 379;
				$currentBox.stop().animate({
					'top'     : '0px',
					'left'    : '0px',
					'width' : newwidth +'px',
					'height': newheight+'px'
				},800,'easeOutBack',function(){
					current = $currentBox.index();
					$(this).find('.boxcontent').fadeIn();
				});
			}
			e.preventDefault();
	});
});

Sekcja 4Demo z artykułu

Wpis w oryginalnej wersji można znaleźć na stronie. Jego przedruk został napisany przeze mnie, dzięki współpracy z autorem. Demo z tego artykułu można zobaczyć w tym miejscu: jQuery menu z kwadratami
Udostępnij
Uwagi

O autorze

Staff Software Engineer

Piszę na tym blogu od 2009 roku, a strony i aplikacje webowe tworzę zawodowo od 14 lat. Obecnie w Bishop Fox prowadzę frontend platformy Cosmos, od samego początku projektu. Wcześniej pracowałem m.in. w OLX, KUDO, Auto1 i eZ Systems. Piszę tu o tym, czego nauczyłem się w praktyce: o JavaScripcie, TypeScripcie, Reakcie, CSS-ie i architekturze frontendu. Występowałem też jako prelegent na konferencjach w Polsce i Europie. Masz pytanie albo pomysł na wpis? Daj znać!