# Unordered list in HTML with animated list points

I had this idea today, but I don't have any practical usage for it right now. Any feedback or improvements welcome.

Code is found at CodePen, and also presented here as a snippet:

ul {
list-style-type: none;
width: 250px;
border: 2px solid #a9a9a9;
margin: 0 auto;
}

.item {
margin: 10px 0;
}

.point {
display: inline-block;
width: 20px;
height: 20px;
margin-right: 20px;
transform: rotate(0deg);
}

.point:hover {
transform: rotate(-45deg);
}

.text {
display: inline-block;
width: 200px;
color: #121212;
font-family: helvetica;
}

li:nth-of-type(1) div:first-child {
background-color: rgba(30, 30, 30, 1.0);
}

li:nth-of-type(2) div:first-child {
background-color: rgba(60, 60, 60, 1.0);
}

li:nth-of-type(3) div:first-child {
background-color: rgba(90, 90, 90, 1.0);
}

li:nth-of-type(4) div:first-child {
background-color: rgba(120, 120, 120, 1.0);
}

li:nth-of-type(5) div:first-child {
background-color: rgba(150, 150, 150, 1.0);
}
<ul>
<li class="item">
<div class="point"></div>
<div class="text">Alpha</div>
</li>

<li class="item">
<div class="point"></div>
<div class="text">Beta</div>
</li>

<li class="item">
<div class="point"></div>
<div class="text">Gamma</div>
</li>

<li class="item">
<div class="point"></div>
<div class="text">Delta</div>
</li>

<li class="item">
<div class="point"></div>
<div class="text">Epsilon</div>
</li>
</ul>

• The .point elements are unnecessary and can be replaced by using the pseudo-element ::before. This requires adding the property content: "".
• Generally as a rule, it's wrong to use the same class on all child elements, especially when it's generic like item. Better mark the list itself and use a child selector to select the items, for example .animated-list > li.
• The <div class="text"> also seem unnecessary for this example. Setting display: inline-block and width have nothing to do with animated bullets and the color and font-family should be assigned on a higher level element such as the body.

In the CSS, as mentioned above

• replace ul with ul.animated-list
• replace .item with ul.animated-list > li
• replace .point with ul.animated-list > li::before

The sudden use of :first-child instead of .point seems strange. Use ul.animated-list > li::before here too, thus ul.animated-list > li:nth-of-type(1)::before.

Finally, I'd expect the the bullets to animate when hovering over the list item not just the bullet itself, so I'd replace .point:hover with ul.animated-list > li:hover::before.

And for some "flair" consider adding transition: transform 0.1s; to get a smooth animation.

EDIT: Here's my code: http://codepen.io/anon/pen/adoWxp

• Nice comprehensive list, + for reflection on the use of :before. – Gabor Dec 2 '15 at 10:36
• Instead of :nth-of-type(), just use :nth-child(). It may improve the performance of your selectors, since :nth-child() only selects the nth element, regardless of it's "type". Since this is an <ul>, I wouldn't expect anything else other than <li> inside it. Also, to speed up the selectors, you can use .animated-list instead of ul.animated-list and .animated-list li instead of ul.animated-list > li. Read more on developer.mozilla.org/en-US/docs/Web/Guide/CSS/… – Ismael Miguel Dec 2 '15 at 11:52
• @IsmaelMiguel I think you misunderstand the problems with the child selector. .animated-list li is slower than .animated-list > li. If you don't want a child selector you need assign a class to all li, for example, .animated-list__item as suggested by BEM and use that. I personally find ul.animated-list > li better. The performance problems are negligible and it is clearer, especially for a beginner. – RoToRa Dec 2 '15 at 12:20
• Both the OP's and your solution has no list marker if adding more than 5 elements. Do you know if it's possible to work around that issue? Is is possible to set the color on first element, and let next elements have 90% on each color channel related to previous element, or something similar? – holroy Dec 2 '15 at 16:09
• @holroy You could create a repeated pattern with :nth-child(): :nth-child(5n+1) for the 1st, 6th, 11th etc. item, :nth-child(5n+2) for the 2nd, 7th, 12th, etc. and so on. – RoToRa Dec 3 '15 at 15:24

Assuming you wish to have your bullet points with the same color (but with different intensity), we could cut back a bit on the multiple definitions of background-color and just modify opacity as such:

.point {
display: inline-block;
width: 20px;
height: 20px;
margin-right: 20px;
transform: rotate(0deg);

transition: transform 0.6s; /* for smoother animation */
background-color: rgba(30, 30, 30, 1.0); /* base color which we'll modify */
}

li:hover .point{
transform: rotate(-45deg);
}

li:nth-of-type(2) div:first-child  {
opacity:0.8;
}

li:nth-of-type(3) div:first-child  {
opacity:0.6;
}

li:nth-of-type(4) div:first-child {
opacity:0.4;
}

li:nth-of-type(5) div:first-child {
opacity:0.2;
}


I've also added in a transition for .point for smoother animation. Normally users move their mouse over the text component of such lists not the bullet-item, so a slight addition to the :hover part will make your animation more apparent.

You're not doing any heavy lifting on your li.items and even in the nth-of-type section you're just referring to the lis, so you could switch the .item{} to ul > li{} ( the > depicting direct children of the left-hand element). With that we can remove the class="item" definitions from the HTML reducing character output.

Misc note that depending on whether you'd want to use .text and .point in different contexts on your page, you might want to move related css definitions under the ul tag (same chain of thought applies for the ul, if you want all your uls to look like this, then of course this is suffice, but if you wanted other kinds, you might want to add a class to this type of ul, eg. ul.leaflist).

Working example: http://jsfiddle.net/u8vt5sqf/

So far most of the solutions, including the solution by OP, will stop having list markers with more than 5 elements in the list, which is a show-stopper for me.

The ideal solution in my mind, would be to make the next color at a given percentage of previous color. But that requires programming, as far as I know. Another solution to make the list marker keep appearing is to extend the nth-of-type-selector using formulas, see css-tricks.com :nth-of-type.

This explains how you can write :nth-of-type(an+b), where a represent the repeat factor, n is literal, + (or -) indicates addition/subtraction, and b is offset. In other words, if you use 5n+1 it denotes the 1st, 6th, 11th, ... elements, and 5n+2 denotes the 2nd, 7th, 8th, ... elements.

In the code below, based on RoToRa's answer, I've only changed the :nth-of-type(...) selectors into :nth-of-type(5n+x) (with x varying from 1 through 5. This repeats the formatting for every 5th element.

ul.animated-list {
list-style-type: none;
width: 250px;
border: 2px solid #a9a9a9;
margin: 0 auto;
}

ul.animated-list > li {
margin: 10px 0;
}

ul.animated-list > li::before {
content: "";
display: inline-block;
width: 20px;
height: 20px;
margin-right: 20px;
transform: rotate(0deg);
transition: transform 0.1s;
}

ul.animated-list > li:hover::before {
transform: rotate(-45deg);
}

ul.animated-list > li:nth-of-type(5n+1)::before {
background-color: rgba(30, 30, 30, 1.0);
}

ul.animated-list > li:nth-of-type(5n+2)::before  {
background-color: rgba(60, 60, 60, 1.0);
}

ul.animated-list > li:nth-of-type(5n+3)::before {
background-color: rgba(90, 90, 90, 1.0);
}

ul.animated-list > li:nth-of-type(5n+4)::before {
background-color: rgba(120, 120, 120, 1.0);
}

ul.animated-list > li:nth-of-type(5n+5)::before {
background-color: rgba(150, 150, 150, 1.0);
}
<ul class="animated-list">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
<li>Delta</li>
<li>Epsilon</li>
<li>Zeta</li>
<li>Eta</li>
<li>Theta</li>
<li>Iota</li>
<li>Kappa</li>
<li>Lambda</li>
</ul>

If modifiying to include the opacity suggested by Gabor, one can use the concept of a base color, and with some slight justification to the base rotation, and implementation of the down-and-up scheme, one gets the following snippet:

ul.animated-list {
list-style-type: none;
width: 250px;
border: 2px solid #a9a9a9;
margin: 0 auto;
}

ul.animated-list > li {
margin: 10px 0;
}

ul.animated-list > li::before {
content: "";
display: inline-block;
width: 15px;
height: 10px;
margin-right: 20px;
transform: rotate(-15deg);
transition: transform 0.1s;
background-color: rgb(51, 166, 214); # Base color
}

ul.animated-list > li:hover::before {
transform: rotate(-60deg);
}

/* Not needed when doing opacity on background.color
ul.animated-list > li:nth-of-type(8n+1)::before {
background-color: rgba(30, 30, 30, 1.0);
} */

ul.animated-list > li:nth-of-type(8n+2)::before {
opacity: 0.8;
}

ul.animated-list > li:nth-of-type(8n+3)::before {
opacity: 0.6;
}

ul.animated-list > li:nth-of-type(8n+4)::before {
opacity: 0.4;
}

ul.animated-list > li:nth-of-type(8n+5)::before {
opacity: 0.2;
}

ul.animated-list > li:nth-of-type(8n+6)::before {
opacity: 0.4;
}

ul.animated-list > li:nth-of-type(8n+7)::before {
opacity: 0.6;
}

ul.animated-list > li:nth-of-type(8n+8)::before {
opacity: 0.8;
}
<ul class="animated-list">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
<li>Delta</li>
<li>Epsilon</li>
<li>Zeta</li>
<li>Eta</li>
<li>Theta</li>
<li>Iota</li>
<li>Kappa</li>
<li>Lambda</li>
</ul>