Transcript
This transcript was autogenerated. To make changes, submit a PR.
You.
Hi all, I am glad to welcome everyone to this wonderful meeting.
In today's talk, I will tell you about how I have solve the problem
of reusable skeleton loaders and turn it into my own open
source CSS library, skeleton mammoth before starting
my speech, I want to introduce myself with a couple of facts. My name
is Alexander Tskochenka. I have about five years of experience in it sphere
in total, author of technical and scientific articles, hackathons,
referring conferences, speaker and of course creator of the
skeleton Mammoth open source CSS library. So let's
get started. There are a lot of great articles on the Internet
devoted to skeleton loaders covering their types, cases and needs
for their use. After investigating this topic in detail,
I came to the conclusion that each example already made solution is
unique and good on its own way, but in most cases
they are suitable for a specific scenario rather than for universal use. For many
scenarios, these prompted me to create my own reusable and customizable
solutions that would suit most use cases and what
are skeleton loaders? A skeleton loader, also known as a skeleton screen
or content placeholder, is a user interface design pattern used to enhance
the user experience during content loading in web and mobile applications.
When data is being fetched or processed in the background, instead of
displaying a blank connective screen, a skeleton loader mimics
page layout by providing users with a visual cue of
what to expect, reducing perceived loading times and mitigation.
Potential frustration many well known large websites
use curtain loaders and here are some examples. These are examples
of skeletons used on YouTube on the left side and LinkedIn
on the right side. But why do we have to use
skeleton loaders at all? Good question. In an attempt to
answer this question briefly, I have outlined several main reasons for using
skeleton loaders. But if you investigate this question separately,
you can get a lot more information for yourself.
And the first one is improve user experience. Skeleton loaders enhance
the user experience by providing visual feedback and reducing the perception
of content. Loading delays another one is reduced bounce
rate. Yes, skeleton loaders can prevent users from leaving the page
due to the loading delays. Another one is smooth
transitions. They create smoother transition between different sites
of a page or application and one more it's focus
attention, unlike other alternative skeleton loaders attract the user
attention to progress rather than waiting time.
And here's the problems of mostly existing skeletons.
Taking into account that there are a lot of examples of creating your own skeleton
loaders or libraries that did it for you, there are still number of
concerns with them. And here's its list limited customization
many exited in skeletons have limited customization options. It leads
to a mismatch of the actual content design and skeleton style.
Another one is empowerment user support. Although their purpose
is to provide a visual representation, most of them are not adapted to
users with visual impairments or those who use screen readers.
Another one is versatility and visibility.
Most approaches to creating skeletons offer either creating a
shallow copy of a component's placeholders, resulting in many and
many similar copies, or essentially changing the structure of existing components.
Both of the approaches require a lot of additional code and assets.
One more maintenance complexity. As a website evolve
and content changes, keeping skeleton loaders up to date can become
a maintenance burden and another one bind to a
specific framework library. Often, ready made solutions are
either only stacked for certain frameworks such as react js or Vue
js, or they are parts of a larger library.
So, for example, if you only want to use skeleton from a popular libraries
like MUI, you still need to install its core files or component of that
library to use only one skeleton from there.
Alternatives there are several alternatives to using
skeletons, looking ahead and answering whether they are really
alternatives. My answer is no, rather than yes.
If we talk about correct usage, then the skeleton is one of the best solutions.
But still, let's consider a couple of alternatives along with their pros and cons.
And first of them is spinner. Spinner is a common
alternative to skeleton loaders. They consist of animated icons
that rotate continuously, providing a visual cue that the content is loading.
You can see it on the slide. To the pros of spinners I can
say its simplicity simple implementations that often requires only a
few lines of code or using predesigned libraries. And of course
it's a universal understanding. Spinners are widely recognized across
different platforms and applications, ensuring that users
understand that content is loading. To the columns of spinner
I could attribute limited information. Spinners do
not provide any context about the content is being
loaders overlap the entire page almost of it, not individual
elements. It gives the feeling of loading not individual elements of
the page, but the entire site as a whole. So spinners
are integral part of interfaces, but they are not exactly suitable for replacing skeletons.
Another one is a progress bar. A progress bar is a visual
element that indicates the completion status of a task or process.
It provides a linear representation, typically with a field portion
that grows gradually. The process of progress bar I could
attribute precise feedback that provides accurate and precise feedback
on the completion status of a task. Its time estimation progress
bar can give user estimate of remaining time required for completion
and its multipurpose progress bar can be used in various
contexts and scenarios, making them a versatile component in web and
application development. But for the cons of the spin
progress bars, I could say it's lack of context. In some cases,
progress bars might not provide sufficient context about the actual task
approaches they represent and implementation complexity.
Creating progress bar with accurate representation and smooth animations
can be complex, especially when dealing with varying tasks,
durations and responsiveness. Process bar are more suitable for
scenarios showing the progress of a file, upload or quantity of progress.
They are often used at the top of the pages to show the progress of
an entire page loading. However, they cannot serve as
an equivalent replacement for the skeleton because they are intended for other purposes
and another one is absence of any visual yeah,
not having any loaders or placeholders is also an alternative,
and in some cases this will be a better solution than using unsuitable
elements, the main and probably the only process that you
don't need additional time and resources spent on implementations.
But here come the obvious cons, a less attractive design for your site,
and the perception of slower loading time.
Creating versatile and reusable skeleton
after I had gained enough knowledge of what skeletons are, when to
use them and approaches to their development, I tried to determine for myself
what my final result should be. These are the key requirements that
I wanted to have present and my final result. So first,
it's versatile and reusable. There are a lot
of examples over the Internet with overcomplicated
approaches where you have to create a separate skeleton for every component you
want to have them on. In my cases, I want it to be something
singular that can be reused for most cases and not stick to any JavaScript
framework like react of you. The second one is configuration
flexibility. Since every project and every case can be
very different, my skeleton needed to be able to be configurable.
Another one is future reach. Yeah, it's just a simple skeleton,
but in addition to the standard set of features, I wanted to fill it with
support for additional useful and necessary features. And last
but not least, lightweight and dependencies free, lightweight and
as free as possible from other third party dependencies.
All of these expectations and investigations led me to the
fact that my future skeleton had to be written in pure CSS without
any JavaScript and third party dependencies.
This makes it possible to be lightweight and dependencies free.
The main idea that it inherits layouts of components it applied
to and customize them with their own styles over
time for development purposes, I have rewritten
CSS syntax to SCSS. This made it possible to decompose
the code for smaller logical parts, make it more concise and
reusable, but the end result to the end compiled result is still
pure CSS without any dependencies. Base card
as a basic example and for demo purposes I will use react and take
some base card markup to show how it works, but I remind you that it's
not tied to any of the frameworks. Here is a card markup example
that has its own styles and doesn't know about the existence of
skeletons yet. It's just an ordinary card with an image and two
text fields. You can see it's a parent class card
in the parent div and some child divs with the card image wrapper
and card body with title and subtitle.
In order for the skeleton to become active, it's only necessary to
apply the parent class SM loading to the card itself and the child
classes smitem primary or smitem secondary to those elements on which
we want to see the skeleton so the
updated result will look like this. Let me break it down and explain
in a few moments. On the first line of code, I apply a
same loading class depending on the condition. If the status
of the datastate datastat is equal to loading,
then the class will be applied. Otherwise, no,
the same loading class should only be set or present
while your data is loading. It's kind of a feature to turn on
or turn off the skeleton. So only when at present, child elements
with the presence of appropriate classes smitem primary
and the same item secondary will display the skeleton.
Lines two, seven and eight of the code contain classes to
show the skeleton on these elements. So only three classes will make this skeleton
to work. Root variables colors let's take a
little look under the hood and if you can clearly see what's shown
on this slide, that's okay. The main idea is to show how everything
works for usability as well as an advanced usage
of the skeleton, which I will discuss later. The main style values
are variables paste in the CSS root pseudoclass.
This particular slide shows that every color value is placed inside
the variable inside the CSS root pseudoclass. You can see it here.
The same for animations. All values for animation
management are in variables placed inside the root CSS pseudoclass.
It's like duration, time and function, et cetera.
Base styles this slide depict the base style
that don't relate to any color scheme or configuration. The main idea
in my approach is that the solution should be reusable and does not have
to be customized separately for each component.
As stated earlier, parent class sm loading is
used to activate the skeleton loader style. You can see it here.
The semitetem primary and smitem secondary classes override an
element style and display the skeleton. In this way.
The layout styles and dimensions of elements in our case it's
base card component, are persisted and inherited by
the skeleton loaders. So you don't need to specify width or height of the skeleton.
It's inherited by the base components. In our case it's base card.
Additionally, I would like to say that with this approach we guarantee that
all child elements of the smitem primary class or
smitem secondary are hidden and at least have a non
creating space character. You can see it here. So if we have,
let's say some empty div that doesn't have a content, but we have applied the
smitem primary or secondary class, it will be shown in
any way and rendered. If an element contains no
content at all, the symbol ensures that the element is displayed and rendered.
There is also a part that is responsible for users of screen readers
and let them know that the content is in the process of loading. You can
see it in the middle of the slide. The main idea of
these basic styles is to hide all unnecessary visual elements
such as borders, placeholders, et cetera, so you can
apply your own skeleton styles structure
here is a visual representation of what the base card components
looks like. You can see like say our imaginary website and
our base card component. The card has a class same loading
to turn on the skeleton. So this card itself has class
card and SM loading class. The elements on which
the skeleton is displayed have corresponding classes,
smitem primary and SM item secondary.
Here you can see this image of the card with Smitem primary class
and two fields with smitem secondary like title and subtitle
advanced features in addition to the main functionality, it's good to
have additional features to satisfy as many users needs as possible and
cover as many use cases as possible. And first feature is
color scheme with the CSS media feature prefers
color scheme I have implemented automatic support of the light and dark themes.
Depending on the user settings, it will be applied automatically. Of course
it's possible to set it manually. I'll talk about it later in
the documentation. In the presentation. Another one is
reduced motion by default. In the skeleton I decided to make animation
enabled, but there are cases when developers or users
would prefer not to have it, and if for the former this may
be dictated by design and requirements, then for the latter, it may
be due to the vestibular motion disorders. For this,
the CSS media feature prefers reduced motion comes to the rescue.
Whenever a user had these settings enabled, let's say on their
laptop. On any other device, the animation will be disabled
and configuration. At this stage the main styles are over
and the skeleton can be considered ready. But I was haunted
by the thought that I should be able to configure all of the above.
What if I want to turn off the animation? What if I want to always
have a dark theme? Since it's not possible for CSS to receive
any values as arguments like JavaScript functions do, the addition
of JavaScript was excluded, at least at this stage, because it
will completely break the main concept of being as simple as possible.
But still, we can implement something similar to arguments if you know their
values in advance. And here that data attributes came to
error eight. With their help, we can check for the presence of
the value we need in the attribute and apply the desired style. That's simple.
For example, if you want to explicitly set the animation theme and
the varsity settings, you need to make a JSON object as shown on the top
code snippet. You can see it here. It's still our base card with
some variable config that's wrapped in the JSON stringify method, and we
set predefined fields like animation type, theme, and opacity.
Next, pipe this object to the custom attribute data SM config on
the same layer as the SM loading class shown on the lower code snippet.
And that's all. Here's what it looks like in the compiled
CSS when a user sets only a theme configuration.
Thus, using an attribute selection, we match elements that have an
explicitly specified attribute and its values.
This allow us to apply different style depending on the given attribute values.
Advanced usage each project and case is
unique, and it's impossible to predict and make everything versatile.
Yeah, especially when it comes to colors. That is why,
as I said earlier, most of the values are placed in variables
in CSS root pseudoclass. If you want to
adjust the default styles, just overwrite appropriate variables
in your own CSS file inside the root CSS pseudoclass.
So, for example, if you want to change the color of the primary item with
the class smitem primary, you only need to override the corresponding
variable, and that's all the same for animations. Most of
the animation settings, like their duration, time functions,
et cetera, could be overridden with the same approach.
In this way, it gives us the full freedom of action in terms of customization,
of course. To make the work easier and clearer, I made a well described
documentation section that contains all the variables available for overriding
and usage examples and moving from theory to practice.
Let's take a look at a demo using a tinched result and its capabilities.
Here's what a working skeleton for card components looks like.
The quality of the picture may not be very good since this is a GIF
animation converted from a video file, but anyway,
once the data has loaded, the skeleton disappears and you display
the loaded content to the user. At the same time, you can develop
transitions between the skeleton and the content yourself for a smooth
flow. As you can see on this slide how it smoothly transitioned.
This slide showed support for the dark color scheme,
which, as I said, is either turned on automatically in the absence of
explicitly specified settings, or is set up
using a configuration object. For the demo purposes, it's using
configuration object and sets up manually so I can switch
the skeleton theme and website theme to the dark and light themes animations
out of the box there's support for different animations as
well as the ability to turn it off so you can see on
the slide different types of animations. We can turn it off
by pressing none. We can set wave animations from left
to right, wave reverse from right to left, and pulse
animation. It's like blinking and opacity.
This slide showed the ability to set the opacity of the skeleton.
This is done because standard colors may not always suit your design,
but in order to adjude them to your design, you just need to play with
the opacity property without having to completely override the colors.
So let's wrap it up. After I had studied the topic of skeleton
loaders for a long time, their varieties, usage and approaches to development,
I managed to collect the sense of useful information and turn it into a final
product. Having collected best practices, improved them and
combined them into a single entity. I have created a library called skeleton
mammoth. I believe that I managed to achieve my goals
and create a pretty good library with all of the advantages described
in this presentation. I hope that this library is able to benefit
people when using it, or provide new knowledge and experience as a starting
point to create something of their own. If you find
my speech useful and would like to show your support, there's a simple way to
do so. And first of them, it starts a GitHub repository.
This helps to increase its visibility and lets others know that the library has a
strong user base and of course spreads the world.
You can introduce new users to the library by sharing information about
its unending platform, such as writing about in a blog post,
mentioning social media, or discuss in relevant developer communities.
It's very crucial for me to receive feedback on my library and I warmly
welcome new contributors and any suggestions for improvement.
Thank you for your attention. By scanning this QR code, you will find useful
links such as my LinkedIn, Instagram, a link to the library itself,
and slide and presentation text. Wish you all the
best.