Twitter’s Like button as Salesforce Lightning Component- pure CSS3 with Video

Building Lightning component checkbox to have Twitter’s Heart like animation without any image or JavaScript.

Twitter Heart Animation using pure CSS3

Twitter uses image sprite and JavaScript to produce Like button animation. We would be giving same effect to checkbox by using Lightning component. Combination of Checkbox, Label and Box property of CSS3 is used to give final result.

Lightning Component will contain only declaration of checkbox as shown below.

TwitterLove.cmp


<aura:component >
<input id="toggle-heart" type="checkbox" />
<label for="toggle-heart">❤</label>
</aura:component>

Note : In above source code, heart UTF icon is getting replaced by emoji code, so refer this screen to see exact code written for Lightning Component.

We have used Sassy CSS (SCSS) in this demo, as it would be little bit hard to write pure CSS with animation. Once SCSS is written, we can use this online tool to convert it to CSS. All these are explained and build live on my channel.

TwitterLove.scss


$bubble-d: 4.5rem; // bubble diameter
$bubble-r: .5*$bubble-d; // bubble-radius
$particle-d: .375rem;
$particle-r: .5*$particle-d;

$shadow-list: (); // init shadow list
$n-groups: 7.0; // number of groups
$group-base-angle: 360deg/$n-groups;
$group-distr-r: 1.0 * $bubble-r; // circular distribution radius for groups
@for $i from 0 to $n-groups {
// current group angle, starting fron 12 o'clock
$group-curr-angle: $i * $group-base-angle - 90deg;
// coords of the central point of current group of particles
$xg: $group-distr-r * cos($group-curr-angle);
$yg: $group-distr-r * sin($group-curr-angle);

// add to shadow list
$shadow-list: $shadow-list, $xg $yg;
}

@mixin bubble($ext) {
transform: scale(1);
border-color: #cc8ef5;
border-width: $ext;
}

body {
display: flex;
justify-content: center;
margin: 0;
height: 100vh;
}

[id='toggle-heart'] {
position: absolute;
left: -100vw;

&:checked + label {
color: #e2264d;
will-change: font-size;
animation: heart 1s cubic-bezier(.17, .89, .32, 1.49);

&:before, &:after {
animation: inherit;
animation-timing-function: cubic-bezier(.21, .61, .35, 1);
}

&:before {
will-change: transform, border-width, border-color;
animation-name: bubble;
}
}
}

[for='toggle-heart'] {
align-self: center;
position: relative;
color: #aab8c2;
font-size: 2em;
cursor: pointer;

&:before, &:after {
position: absolute;
z-index: -1;
top: 50%; left: 50%;
border-radius: 50%;
content: '';
}

&:before {
box-sizing: border-box;
margin: -$bubble-r;
border: solid $bubble-r #e2264d;
width: $bubble-d; height: $bubble-d;
transform: scale(0);
}

&:after {
margin: -$particle-r;
width: $particle-d; height: $particle-d;
box-shadow: $shadow-list;
}
}

@keyframes heart {
0%, 17.5% { font-size: 0; }
}

@keyframes bubble {
15% { @include bubble($bubble-r); }
30%, 100% { @include bubble(0); }
}

TwitterLove.css (CSS auto generated from SCSS)


.THIS {
display: flex;
justify-content: center;
margin: 0;
}

.THIS[id='toggle-heart'] {
position: absolute;
left: -100vw;
}

.THIS[for='toggle-heart'] {
color: #aab8c2;
}

.THIS[id='toggle-heart']:checked + label {
color: #e2264d;
}

.THIS[for='toggle-heart'] {
font-size: 2em;
cursor: pointer;
}

.THIS[for='toggle-heart'] {
align-self: center;
margin-top: 100px;
}

@keyframes heart {
0%, 20% {
font-size: 0;
}
}
.THIS[id='toggle-heart']:checked + label {
will-change: font-size;
animation: heart 1s cubic-bezier(0.17, 0.89, 0.32, 1.49);
}

.THIS[for='toggle-heart'] {
position: relative;
}
.THIS[for='toggle-heart']:before, .THIS[for='toggle-heart']:after {
position: absolute;
z-index: -1;
top: 50%;
left: 50%;
border-radius: 50%;
content: '';
}

.THIS[for='toggle-heart']::before {
margin: -2.25rem;
width: 4.5rem;
height: 4.5rem;
}

.THIS[for='toggle-heart']:before {
box-sizing: border-box;
border: solid 2.25rem #e2264d;
transform: scale(0);
}

@keyframes bubble {
15% {
border-color: #cc8ef5;
border-width: 2.25rem;
transform: scale(1);
}
30%, 100% {
border-color: #cc8ef5;
border-width: 0;
transform: scale(1);
}
}
.THIS[id='toggle-heart']:checked + label::before, .THIS[id='toggle-heart']:checked + label::after {
animation: inherit;
animation-timing-function: cubic-bezier(0.21, 0.61, 0.35, 1);
}
.THIS[id='toggle-heart']:checked + label::before {
will-change: transform, border-color, border-width;
animation-name: bubble;
}
.THIS[id='toggle-heart']:checked + label:after {
will-change: opacity, box-shadow;
animation-name: particles;
}

.THIS[for='toggle-heart']:after {
margin: -0.1875rem;
width: 0.375rem;
height: 0.375rem;
}

@keyframes particles {
0%, 20% {
opacity: 0;
}
25% {
opacity: 1;
box-shadow: 0.32476rem -2.4375rem 0 0rem #ff8080, -0.32476rem -2.0625rem 0 0rem #ffed80, 2.1082rem -1.26585rem 0 0rem #ffed80, 1.41004rem -1.53985rem 0 0rem #a4ff80, 2.30412rem 0.85901rem 0 0rem #a4ff80, 2.08305rem 0.14233rem 0 0rem #80ffc8, 0.76499rem 2.33702rem 0 0rem #80ffc8, 1.18748rem 1.71734rem 0 0rem #80c8ff, -1.35019rem 2.0552rem 0 0rem #80c8ff, -0.60229rem 1.99916rem 0 0rem #a480ff, -2.44865rem 0.22578rem 0 0rem #a480ff, -1.93852rem 0.77557rem 0 0rem #ff80ed, -1.70323rem -1.77366rem 0 0rem #ff80ed, -1.81501rem -1.03204rem 0 0rem #ff8080;
}
}
.THIS[for='toggle-heart']:after {
box-shadow: 0.32476rem -3rem 0 -0.1875rem #ff8080, -0.32476rem -2.625rem 0 -0.1875rem #ffed80, 2.54798rem -1.61656rem 0 -0.1875rem #ffed80, 1.84982rem -1.89057rem 0 -0.1875rem #a4ff80, 2.85252rem 0.98418rem 0 -0.1875rem #a4ff80, 2.63145rem 0.2675rem 0 -0.1875rem #80ffc8, 1.00905rem 2.84381rem 0 -0.1875rem #80ffc8, 1.43154rem 2.22414rem 0 -0.1875rem #80c8ff, -1.59425rem 2.562rem 0 -0.1875rem #80c8ff, -0.84635rem 2.50595rem 0 -0.1875rem #a480ff, -2.99705rem 0.35095rem 0 -0.1875rem #a480ff, -2.48692rem 0.90073rem 0 -0.1875rem #ff80ed, -2.14301rem -2.12438rem 0 -0.1875rem #ff80ed, -2.25479rem -1.38275rem 0 -0.1875rem #ff8080;
}

.THIS[id='toggle-heart']:checked + label:after {
margin: -0.1875rem;
width: 0.375rem;
height: 0.375rem;
/* box-shadow: $shadow-list;*/
box-shadow: 0.32476rem -3rem 0 -0.1875rem #ff8080, -0.32476rem -2.625rem 0 -0.1875rem #ffed80, 2.54798rem -1.61656rem 0 -0.1875rem #ffed80, 1.84982rem -1.89057rem 0 -0.1875rem #a4ff80, 2.85252rem 0.98418rem 0 -0.1875rem #a4ff80, 2.63145rem 0.2675rem 0 -0.1875rem #80ffc8, 1.00905rem 2.84381rem 0 -0.1875rem #80ffc8, 1.43154rem 2.22414rem 0 -0.1875rem #80c8ff, -1.59425rem 2.562rem 0 -0.1875rem #80c8ff, -0.84635rem 2.50595rem 0 -0.1875rem #a480ff, -2.99705rem 0.35095rem 0 -0.1875rem #a480ff, -2.48692rem 0.90073rem 0 -0.1875rem #ff80ed, -2.14301rem -2.12438rem 0 -0.1875rem #ff80ed, -2.25479rem -1.38275rem 0 -0.1875rem #ff8080;
}

Next Step – Handling event in Lightning Component

We can register event on this component, so that whenever checkbox is checked, other components in Lightning components can be notified. This trailhead module would guide in much detail about handling events in Lightning Component.

Resources 

Related posts