chevron-left chevron-right

Piotr Nalepa Frontend, architecture and AI

[CSS][jQuery] Efektowne menu z kwadratami

This version
blog.piotrnalepa.pl/2011/03/28/cssjquery-efektowne-menu-z-kwadratami
Published
Author
, Staff Software Engineer
Categories
CSS, JavaScript
Feedback
Write to me · Post on X

This post is 15 years old. Browsers and tools may have changed since then, so check the code against current documentation before you use it.

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.

Section 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.
Example 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>

Section 2Style CSS

Teraz czas na style CSS, które określą wstępny wygląd naszego menu:
Example 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.

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

Section 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
Share
Feedback

About the author

Staff Software Engineer

I've been writing this blog since 2009 and building for the web professionally for 14 years. Today I lead the frontend of the Cosmos platform at Bishop Fox, where I've been since day one of the project. Before that I worked at OLX, KUDO, Auto1 and eZ Systems. Here I write about what I've learned in practice: JavaScript, TypeScript, React, CSS and frontend architecture. I've also spoken at conferences across Poland and Europe. Got a question or an idea for a post? Let me know!