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;
border-radius: 16px;
margin: 0 auto;
}
.item {
margin: 10px 0;
}
.point {
display: inline-block;
width: 20px;
height: 20px;
margin-right: 20px;
border-radius: 0 50%;
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>
3 Answers 3
Your HTML is far too overloaded.
- The
.point
elements are unnecessary and can be replaced by using the pseudo-element::before
. This requires adding the propertycontent: ""
. - 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. Settingdisplay: inline-block
andwidth
have nothing to do with animated bullets and thecolor
andfont-family
should be assigned on a higher level element such as thebody
.
In the CSS, as mentioned above
- replace
ul
withul.animated-list
- replace
.item
withul.animated-list > li
- replace
.point
withul.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
-
\$\begingroup\$ Nice comprehensive list, + for reflection on the use of
:before
. \$\endgroup\$Gabor– Gabor2015年12月02日 10:36:18 +00:00Commented Dec 2, 2015 at 10:36 -
\$\begingroup\$ 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 oful.animated-list
and.animated-list li
instead oful.animated-list > li
. Read more on developer.mozilla.org/en-US/docs/Web/Guide/CSS/… \$\endgroup\$Ismael Miguel– Ismael Miguel2015年12月02日 11:52:31 +00:00Commented Dec 2, 2015 at 11:52 -
\$\begingroup\$ @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 allli
, for example,.animated-list__item
as suggested by BEM and use that. I personally findul.animated-list > li
better. The performance problems are negligible and it is clearer, especially for a beginner. \$\endgroup\$RoToRa– RoToRa2015年12月02日 12:20:36 +00:00Commented Dec 2, 2015 at 12:20 -
1\$\begingroup\$ 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? \$\endgroup\$holroy– holroy2015年12月02日 16:09:54 +00:00Commented Dec 2, 2015 at 16:09
-
\$\begingroup\$ @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. \$\endgroup\$RoToRa– RoToRa2015年12月03日 15:24:39 +00:00Commented Dec 3, 2015 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;
border-radius: 0 50%;
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.item
s and even in the nth-of-type
section you're just referring to the li
s, 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 ul
s 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;
border-radius: 16px;
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;
border-radius: 0 50%;
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;
border-radius: 16px;
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;
border-radius: 0 50%;
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>