Как сверстать блок облако тегов?

Ссылка скопирована
29 марта 2026 1 ответ

Всем доброго времени суток! Прошу подсказать, каким образом можно сверстать подобное дизайнерское решение?
Так называемое "облако тегов". По задумке, блок должен реагировать на наведение мыши, теги должны немного двигаться в стороны относительно своего текущего расположения. Плюс нужна анимация наведения мыши на конкретный тег - чтобы он становился больше. Какие есть варианты закодить такой блок? Может быть, какую-то библиотеку использовать можно?

Как сверстать блок облако тегов?

Дополнительно:

Если из требований просто движение при наведении+отзывчивый ховер, то думаю подойдет любая библиотека для анимации/руками тоже можно. Я бы смотрел в сторону каввасов/библиотек для графиков типа D3/three.js, но это трудозатратнее

  • https://www.jqueryscript.net/blog/best-tag-cloud.html
  • Kentavr16, Виталий Першин, спасибо большое, пригодилось, получилось :)
  • Ответы:

    1/ а зачем - не очень удобно искать без иерархии и сортировки
    2/ готовые решения - например, Tag cloud generator и т.д.

    • спасибо, пригодилось! :)
    <script>var radius = 120; var dtr = Math.PI/180; var d=300;   var mcList = []; var active = false; var lasta = 1; var lastb = 1; var distr = true; var tspeed=10; var size=250;   var mouseX=0; var mouseY=0;   var howElliptical=1;   var aA=null; var oDiv=null;   window.onload=function () { 	var i=0; 	var oTag=null; 	 	oDiv=document.getElementById('div1'); 	 	aA=oDiv.getElementsByTagName('a'); 	 	for(i=0;i<aA.length;i++) 	{ 		oTag={}; 		 		oTag.offsetWidth=aA[i].offsetWidth; 		oTag.offsetHeight=aA[i].offsetHeight; 		 		mcList.push(oTag); 	} 	 	sineCosine( 0,0,0 ); 	 	positionAll(); 	 	oDiv.onmouseover=function () 	{ 		active=true; 	}; 	 	oDiv.onmouseout=function () 	{ 		active=false; 	}; 	 	oDiv.onmousemove=function (ev) 	{ 		var oEvent=window.event || ev; 		 		mouseX=oEvent.clientX-(oDiv.offsetLeft+oDiv.offsetWidth/2); 		mouseY=oEvent.clientY-(oDiv.offsetTop+oDiv.offsetHeight/2); 		 		mouseX/=5; 		mouseY/=5; 	}; 	 	setInterval(update, 30); };   function update() { 	var a; 	var b; 	 	if(active) 	{ 		a = (-Math.min( Math.max( -mouseY, -size ), size ) / radius ) * tspeed; 		b = (Math.min( Math.max( -mouseX, -size ), size ) / radius ) * tspeed; 	} 	else 	{ 		a = lasta * 0.98; 		b = lastb * 0.98; 	} 	 	lasta=a; 	lastb=b; 	 	if(Math.abs(a)<=0.01 && Math.abs(b)<=0.01) 	{ 		return; 	} 	 	var c=0; 	sineCosine(a,b,c); 	for(var j=0;j<mcList.length;j++) 	{ 		var rx1=mcList[j].cx; 		var ry1=mcList[j].cy*ca+mcList[j].cz*(-sa); 		var rz1=mcList[j].cy*sa+mcList[j].cz*ca; 		 		var rx2=rx1*cb+rz1*sb; 		var ry2=ry1; 		var rz2=rx1*(-sb)+rz1*cb; 		 		var rx3=rx2*cc+ry2*(-sc); 		var ry3=rx2*sc+ry2*cc; 		var rz3=rz2; 		 		mcList[j].cx=rx3; 		mcList[j].cy=ry3; 		mcList[j].cz=rz3; 		 		per=d/(d+rz3); 		 		mcList[j].x=(howElliptical*rx3*per)-(howElliptical*2); 		mcList[j].y=ry3*per; 		mcList[j].scale=per; 		mcList[j].alpha=per; 		 		mcList[j].alpha=(mcList[j].alpha-0.6)*(10/6); 	} 	 	doPosition(); 	depthSort(); }   function depthSort() { 	var i=0; 	var aTmp=[]; 	 	for(i=0;i<aA.length;i++) 	{ 		aTmp.push(aA[i]); 	} 	 	aTmp.sort 	( 		function (vItem1, vItem2) 		{ 			if(vItem1.cz>vItem2.cz) 			{ 				return -1; 			} 			else if(vItem1.cz<vItem2.cz) 			{ 				return 1; 			} 			else 			{ 				return 0; 			} 		} 	); 	 	for(i=0;i<aTmp.length;i++) 	{ 		aTmp[i].style.zIndex=i; 	} }   function positionAll() { 	var phi=0; 	var theta=0; 	var max=mcList.length; 	var i=0; 	 	var aTmp=[]; 	var oFragment=document.createDocumentFragment(); 	 	// Случайная сортировка 	for(i=0;i<aA.length;i++) 	{ 		aTmp.push(aA[i]); 	} 	 	aTmp.sort 	( 		function () 		{ 			return Math.random()<0.5?1:-1; 		} 	); 	 	for(i=0;i<aTmp.length;i++) 	{ 		oFragment.appendChild(aTmp[i]); 	} 	 	oDiv.appendChild(oFragment); 	 	for( var i=1; i<max+1; i++){ 		if( distr ) 		{ 			phi = Math.acos(-1+(2*i-1)/max); 			theta = Math.sqrt(max*Math.PI)*phi; 		} 		else 		{ 			phi = Math.random()*(Math.PI); 			theta = Math.random()*(2*Math.PI); 		} 		 // Преобразование координат 		mcList[i-1].cx = radius * Math.cos(theta)*Math.sin(phi); 		mcList[i-1].cy = radius * Math.sin(theta)*Math.sin(phi); 		mcList[i-1].cz = radius * Math.cos(phi); 		 		aA[i-1].style.left=mcList[i-1].cx+oDiv.offsetWidth/2-mcList[i-1].offsetWidth/2+'px'; 		aA[i-1].style.top=mcList[i-1].cy+oDiv.offsetHeight/2-mcList[i-1].offsetHeight/2+'px'; 	} }   function doPosition() { 	var l=oDiv.offsetWidth/2; 	var t=oDiv.offsetHeight/2; 	for(var i=0;i<mcList.length;i++) 	{ 		aA[i].style.left=mcList[i].cx+l-mcList[i].offsetWidth/2+'px'; 		aA[i].style.top=mcList[i].cy+t-mcList[i].offsetHeight/2+'px'; 		 		aA[i].style.fontSize=Math.ceil(12*mcList[i].scale/2)+8+'px'; 		 		aA[i].style.filter="alpha(opacity="+100*mcList[i].alpha+")"; 		aA[i].style.opacity=mcList[i].alpha; 	} }   function sineCosine( a, b, c) { 	sa = Math.sin(a * dtr); 	ca = Math.cos(a * dtr); 	sb = Math.sin(b * dtr); 	cb = Math.cos(b * dtr); 	sc = Math.sin(c * dtr); 	cc = Math.cos(c * dtr); }</script>

    <script>var radius = 120; var dtr = Math.PI/180; var d=300; var mcList = []; var active = false; var lasta = 1; var lastb = 1; var distr = true; var tspeed=10; var size=250; var mouseX=0; var mouseY=0; var howElliptical=1; var aA=null; var oDiv=null; window.onload=function () { var i=0; var oTag=null; oDiv=document.getElementById('div1'); aA=oDiv.getElementsByTagName('a'); for(i=0;i<aA.length;i++) { oTag={}; oTag.offsetWidth=aA[i].offsetWidth; oTag.offsetHeight=aA[i].offsetHeight; mcList.push(oTag); } sineCosine( 0,0,0 ); positionAll(); oDiv.onmouseover=function () { active=true; }; oDiv.onmouseout=function () { active=false; }; oDiv.onmousemove=function (ev) { var oEvent=window.event || ev; mouseX=oEvent.clientX-(oDiv.offsetLeft+oDiv.offsetWidth/2); mouseY=oEvent.clientY-(oDiv.offsetTop+oDiv.offsetHeight/2); mouseX/=5; mouseY/=5; }; setInterval(update, 30); }; function update() { var a; var b; if(active) { a = (-Math.min( Math.max( -mouseY, -size ), size ) / radius ) * tspeed; b = (Math.min( Math.max( -mouseX, -size ), size ) / radius ) * tspeed; } else { a = lasta * 0.98; b = lastb * 0.98; } lasta=a; lastb=b; if(Math.abs(a)<=0.01 && Math.abs(b)<=0.01) { return; } var c=0; sineCosine(a,b,c); for(var j=0;j<mcList.length;j++) { var rx1=mcList[j].cx; var ry1=mcList[j].cy*ca+mcList[j].cz*(-sa); var rz1=mcList[j].cy*sa+mcList[j].cz*ca; var rx2=rx1*cb+rz1*sb; var ry2=ry1; var rz2=rx1*(-sb)+rz1*cb; var rx3=rx2*cc+ry2*(-sc); var ry3=rx2*sc+ry2*cc; var rz3=rz2; mcList[j].cx=rx3; mcList[j].cy=ry3; mcList[j].cz=rz3; per=d/(d+rz3); mcList[j].x=(howElliptical*rx3*per)-(howElliptical*2); mcList[j].y=ry3*per; mcList[j].scale=per; mcList[j].alpha=per; mcList[j].alpha=(mcList[j].alpha-0.6)*(10/6); } doPosition(); depthSort(); } function depthSort() { var i=0; var aTmp=[]; for(i=0;i<aA.length;i++) { aTmp.push(aA[i]); } aTmp.sort ( function (vItem1, vItem2) { if(vItem1.cz>vItem2.cz) { return -1; } else if(vItem1.cz<vItem2.cz) { return 1; } else { return 0; } } ); for(i=0;i<aTmp.length;i++) { aTmp[i].style.zIndex=i; } } function positionAll() { var phi=0; var theta=0; var max=mcList.length; var i=0; var aTmp=[]; var oFragment=document.createDocumentFragment(); // Случайная сортировка for(i=0;i<aA.length;i++) { aTmp.push(aA[i]); } aTmp.sort ( function () { return Math.random()<0.5?1:-1; } ); for(i=0;i<aTmp.length;i++) { oFragment.appendChild(aTmp[i]); } oDiv.appendChild(oFragment); for( var i=1; i<max+1; i++){ if( distr ) { phi = Math.acos(-1+(2*i-1)/max); theta = Math.sqrt(max*Math.PI)*phi; } else { phi = Math.random()*(Math.PI); theta = Math.random()*(2*Math.PI); } // Преобразование координат mcList[i-1].cx = radius * Math.cos(theta)*Math.sin(phi); mcList[i-1].cy = radius * Math.sin(theta)*Math.sin(phi); mcList[i-1].cz = radius * Math.cos(phi); aA[i-1].style.left=mcList[i-1].cx+oDiv.offsetWidth/2-mcList[i-1].offsetWidth/2+'px'; aA[i-1].style.top=mcList[i-1].cy+oDiv.offsetHeight/2-mcList[i-1].offsetHeight/2+'px'; } } function doPosition() { var l=oDiv.offsetWidth/2; var t=oDiv.offsetHeight/2; for(var i=0;i<mcList.length;i++) { aA[i].style.left=mcList[i].cx+l-mcList[i].offsetWidth/2+'px'; aA[i].style.top=mcList[i].cy+t-mcList[i].offsetHeight/2+'px'; aA[i].style.fontSize=Math.ceil(12*mcList[i].scale/2)+8+'px'; aA[i].style.filter="alpha(opacity="+100*mcList[i].alpha+")"; aA[i].style.opacity=mcList[i].alpha; } } function sineCosine( a, b, c) { sa = Math.sin(a * dtr); ca = Math.cos(a * dtr); sb = Math.sin(b * dtr); cb = Math.cos(b * dtr); sc = Math.sin(c * dtr); cc = Math.cos(c * dtr); }</script>

    <style>#div1 { 	position:relative; 	width:450px; 	height:450px; 	margin: 20px auto 0; } #div1 a { 	position:absolute; 	top:0px; 	left:0px; 	font-family: Microsoft YaHei; 	color:#fff;  	font-weight:bold; 	text-decoration:none; 	padding: 3px 6px; } #div1 a:hover { 	border: 1px solid #eee; 	background: #000; } #div1 .blue { 	color:blue; } #div1 .red { 	color:red; } #div1 .yellow { 	color:yellow; }   p { 	font: 16px Microsoft YaHei; 	text-align: center; 	color: #ba0c0c; } p a { 	font-size: 14px; 	color: #ba0c0c; } p a:hover { 	color: red; }</style>

    <style>#div1 { position:relative; width:450px; height:450px; margin: 20px auto 0; } #div1 a { position:absolute; top:0px; left:0px; font-family: Microsoft YaHei; color:#fff; font-weight:bold; text-decoration:none; padding: 3px 6px; } #div1 a:hover { border: 1px solid #eee; background: #000; } #div1 .blue { color:blue; } #div1 .red { color:red; } #div1 .yellow { color:yellow; } p { font: 16px Microsoft YaHei; text-align: center; color: #ba0c0c; } p a { font-size: 14px; color: #ba0c0c; } p a:hover { color: red; }</style>

    <div id="div1"> 	 <a href=""> Пример 1 </a> 	 <a href="" class="red"> Пример два </a> 	 <a href=""> Пример три </a> 	 <a href=""> Пример </a> 	 <a href="" class="blue"> Пример </a> 	 <a href=""> Пример </a> 	 <a href="" class="red"> Пример </a> 	 <a href="" class="yellow"> Пример </a> 	 <a href=""> Пример </a> 	 <a href="" class="red"> Пример </a> 	 <a href=""> Пример </a> 	 <a href="" class="blue"> Пример </a> 	 <a href=""> Пример </a> 	 <a href="" class="red"> Пример </a> 	 <a href="" class="blue"> Пример </a> 	 <a href=""> Пример </a> 	 <a href="" class="blue"> Пример </a> 	 <a href=""> Пример </a> 	 <a href=""> Пример </a> 	 <a href="" class="yellow"> Пример </a> 	 <a href=""> Пример </a> </div>

    <div id="div1"> <a href=""> Пример 1 </a> <a href="" class="red"> Пример два </a> <a href=""> Пример три </a> <a href=""> Пример </a> <a href="" class="blue"> Пример </a> <a href=""> Пример </a> <a href="" class="red"> Пример </a> <a href="" class="yellow"> Пример </a> <a href=""> Пример </a> <a href="" class="red"> Пример </a> <a href=""> Пример </a> <a href="" class="blue"> Пример </a> <a href=""> Пример </a> <a href="" class="red"> Пример </a> <a href="" class="blue"> Пример </a> <a href=""> Пример </a> <a href="" class="blue"> Пример </a> <a href=""> Пример </a> <a href=""> Пример </a> <a href="" class="yellow"> Пример </a> <a href=""> Пример </a> </div>

    Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Игорь Волков Ответ

    Для верстки блока облака тегов можно использовать следующий подход:

    1. Создайте контейнер для блока облака тегов, например,

    .

    2. Внутри контейнера создайте список тегов, например,

      .

      3. Для каждого тега создайте элемент списка

    • , содержащий сам тег. Например,
    • Tag1
    • .

      4. Чтобы стилизовать блок облака тегов, используйте CSS. Ниже приведен пример стилей для блока облака тегов:

      .tag-cloud {
        display: inline-block;
        background-color: #f1f1f1;
        padding: 10px;
        border-radius: 5px;
      }
       
      .tag-list {
        list-style: none;
        padding: 0;
        margin: 0;
      }
       
      .tag-list li {
        display: inline-block;
        margin-right: 10px;
      }
       
      .tag {
        text-decoration: none;
        color: #333;
        background-color: #f9f9f9;
        padding: 5px 10px;
        border-radius: 5px;
      }

      .tag-cloud { display: inline-block; background-color: #f1f1f1; padding: 10px; border-radius: 5px; } .tag-list { list-style: none; padding: 0; margin: 0; } .tag-list li { display: inline-block; margin-right: 10px; } .tag { text-decoration: none; color: #333; background-color: #f9f9f9; padding: 5px 10px; border-radius: 5px; }

      5. Для добавления дополнительного стиля и интерактивности, вы можете использовать псевдоэлементы, анимации, изменение цвета при наведении и т. д.

      Таким образом, следуя этим шагам и примеру стилей, вы сможете легко сверстать блок облака тегов на вашем сайте.

      Другие ответы (0)

      Пока нет других ответов. Будьте первым, кто поможет автору.

      Ответить на вопрос

      комментарий

      Ваш адрес email не будет опубликован. Обязательные поля помечены *

      Вам также может быть интересно