search check home clock-o tag tags chevron-left chevron-right chevron-up chevron-down twitter facebook github rss comment comments terminal code

[CSS][jQuery] Efektowne menu z kwadratami

[CSS][jQuery] Efektowne menu z kwadratami

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.

Struktura 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.

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>

Style CSS

Teraz czas na style CSS, które określą wstępny wygląd naszego menu:

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.

JavaScript

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.

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();
	});
});

Demo 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

  • del

    style w htmlu?…….obrzydlistwo
    specjalista od css – wróć do szkoły

  • Wiem o tym, że style wewnątrz znaczników nie mają racji bytu, ale w tym przypadku pozwalają na ułatwienie kontroli pozycji każdego kontenera. W każdym innym przypadku unikam stosowania „inline-styles”.
    Dlatego też, nie muszę się uczyć pisania CSS od nowa w szkole.
    Zauważ, że we wcześniejszych artykułach, w których poruszany był temat CSS, nie stosowałem stylów wewnątrz tagów HTML.

  • Fajny efekt. Dzięki za art, z pewnością kiedyś go wykorzystam 🙂 W sumie można by było jednak te style przenieść do css i nadać im klasy odpowiednio dla boksów np. boks1, boks2 itp. Wówczas do div’ow wystarczyłoby przypisać klasę odpowiedniego boksu – class=”bg5 boks1″.

  • Jaki problem z przeniesieniem stylów do .css?
    Chyba chodziło o dokładne pokazanie działania…

  • Bardzo ładnie to wyszło i co ważne szybko to działa. Niestety często sztuczki z grafiką w JS bywają piekielnie wolne…