• United States+1
  • United Kingdom+44
  • Afghanistan (‫افغانستان‬‎)+93
  • Albania (Shqipëri)+355
  • Algeria (‫الجزائر‬‎)+213
  • American Samoa+1684
  • Andorra+376
  • Angola+244
  • Anguilla+1264
  • Antigua and Barbuda+1268
  • Argentina+54
  • Armenia (Հայաստան)+374
  • Aruba+297
  • Australia+61
  • Austria (Österreich)+43
  • Azerbaijan (Azərbaycan)+994
  • Bahamas+1242
  • Bahrain (‫البحرين‬‎)+973
  • Bangladesh (বাংলাদেশ)+880
  • Barbados+1246
  • Belarus (Беларусь)+375
  • Belgium (België)+32
  • Belize+501
  • Benin (Bénin)+229
  • Bermuda+1441
  • Bhutan (འབྲུག)+975
  • Bolivia+591
  • Bosnia and Herzegovina (Босна и Херцеговина)+387
  • Botswana+267
  • Brazil (Brasil)+55
  • British Indian Ocean Territory+246
  • British Virgin Islands+1284
  • Brunei+673
  • Bulgaria (България)+359
  • Burkina Faso+226
  • Burundi (Uburundi)+257
  • Cambodia (កម្ពុជា)+855
  • Cameroon (Cameroun)+237
  • Canada+1
  • Cape Verde (Kabu Verdi)+238
  • Caribbean Netherlands+599
  • Cayman Islands+1345
  • Central African Republic (République centrafricaine)+236
  • Chad (Tchad)+235
  • Chile+56
  • China (中国)+86
  • Christmas Island+61
  • Cocos (Keeling) Islands+61
  • Colombia+57
  • Comoros (‫جزر القمر‬‎)+269
  • Congo (DRC) (Jamhuri ya Kidemokrasia ya Kongo)+243
  • Congo (Republic) (Congo-Brazzaville)+242
  • Cook Islands+682
  • Costa Rica+506
  • Côte d’Ivoire+225
  • Croatia (Hrvatska)+385
  • Cuba+53
  • Curaçao+599
  • Cyprus (Κύπρος)+357
  • Czech Republic (Česká republika)+420
  • Denmark (Danmark)+45
  • Djibouti+253
  • Dominica+1767
  • Dominican Republic (República Dominicana)+1
  • Ecuador+593
  • Egypt (‫مصر‬‎)+20
  • El Salvador+503
  • Equatorial Guinea (Guinea Ecuatorial)+240
  • Eritrea+291
  • Estonia (Eesti)+372
  • Ethiopia+251
  • Falkland Islands (Islas Malvinas)+500
  • Faroe Islands (Føroyar)+298
  • Fiji+679
  • Finland (Suomi)+358
  • France+33
  • French Guiana (Guyane française)+594
  • French Polynesia (Polynésie française)+689
  • Gabon+241
  • Gambia+220
  • Georgia (საქართველო)+995
  • Germany (Deutschland)+49
  • Ghana (Gaana)+233
  • Gibraltar+350
  • Greece (Ελλάδα)+30
  • Greenland (Kalaallit Nunaat)+299
  • Grenada+1473
  • Guadeloupe+590
  • Guam+1671
  • Guatemala+502
  • Guernsey+44
  • Guinea (Guinée)+224
  • Guinea-Bissau (Guiné Bissau)+245
  • Guyana+592
  • Haiti+509
  • Honduras+504
  • Hong Kong (香港)+852
  • Hungary (Magyarország)+36
  • Iceland (Ísland)+354
  • India (भारत)+91
  • Indonesia+62
  • Iran (‫ایران‬‎)+98
  • Iraq (‫العراق‬‎)+964
  • Ireland+353
  • Isle of Man+44
  • Israel (‫ישראל‬‎)+972
  • Italy (Italia)+39
  • Jamaica+1876
  • Japan (日本)+81
  • Jersey+44
  • Jordan (‫الأردن‬‎)+962
  • Kazakhstan (Казахстан)+7
  • Kenya+254
  • Kiribati+686
  • Kosovo+383
  • Kuwait (‫الكويت‬‎)+965
  • Kyrgyzstan (Кыргызстан)+996
  • Laos (ລາວ)+856
  • Latvia (Latvija)+371
  • Lebanon (‫لبنان‬‎)+961
  • Lesotho+266
  • Liberia+231
  • Libya (‫ليبيا‬‎)+218
  • Liechtenstein+423
  • Lithuania (Lietuva)+370
  • Luxembourg+352
  • Macau (澳門)+853
  • Macedonia (FYROM) (Македонија)+389
  • Madagascar (Madagasikara)+261
  • Malawi+265
  • Malaysia+60
  • Maldives+960
  • Mali+223
  • Malta+356
  • Marshall Islands+692
  • Martinique+596
  • Mauritania (‫موريتانيا‬‎)+222
  • Mauritius (Moris)+230
  • Mayotte+262
  • Mexico (México)+52
  • Micronesia+691
  • Moldova (Republica Moldova)+373
  • Monaco+377
  • Mongolia (Монгол)+976
  • Montenegro (Crna Gora)+382
  • Montserrat+1664
  • Morocco (‫المغرب‬‎)+212
  • Mozambique (Moçambique)+258
  • Myanmar (Burma) (မြန်မာ)+95
  • Namibia (Namibië)+264
  • Nauru+674
  • Nepal (नेपाल)+977
  • Netherlands (Nederland)+31
  • New Caledonia (Nouvelle-Calédonie)+687
  • New Zealand+64
  • Nicaragua+505
  • Niger (Nijar)+227
  • Nigeria+234
  • Niue+683
  • Norfolk Island+672
  • North Korea (조선 민주주의 인민 공화국)+850
  • Northern Mariana Islands+1670
  • Norway (Norge)+47
  • Oman (‫عُمان‬‎)+968
  • Pakistan (‫پاکستان‬‎)+92
  • Palau+680
  • Palestine (‫فلسطين‬‎)+970
  • Panama (Panamá)+507
  • Papua New Guinea+675
  • Paraguay+595
  • Peru (Perú)+51
  • Philippines+63
  • Poland (Polska)+48
  • Portugal+351
  • Puerto Rico+1
  • Qatar (‫قطر‬‎)+974
  • Réunion (La Réunion)+262
  • Romania (România)+40
  • Russia (Россия)+7
  • Rwanda+250
  • Saint Barthélemy (Saint-Barthélemy)+590
  • Saint Helena+290
  • Saint Kitts and Nevis+1869
  • Saint Lucia+1758
  • Saint Martin (Saint-Martin (partie française))+590
  • Saint Pierre and Miquelon (Saint-Pierre-et-Miquelon)+508
  • Saint Vincent and the Grenadines+1784
  • Samoa+685
  • San Marino+378
  • São Tomé and Príncipe (São Tomé e Príncipe)+239
  • Saudi Arabia (‫المملكة العربية السعودية‬‎)+966
  • Senegal (Sénégal)+221
  • Serbia (Србија)+381
  • Seychelles+248
  • Sierra Leone+232
  • Singapore+65
  • Sint Maarten+1721
  • Slovakia (Slovensko)+421
  • Slovenia (Slovenija)+386
  • Solomon Islands+677
  • Somalia (Soomaaliya)+252
  • South Africa+27
  • South Korea (대한민국)+82
  • South Sudan (‫جنوب السودان‬‎)+211
  • Spain (España)+34
  • Sri Lanka (ශ්‍රී ලංකාව)+94
  • Sudan (‫السودان‬‎)+249
  • Suriname+597
  • Svalbard and Jan Mayen+47
  • Swaziland+268
  • Sweden (Sverige)+46
  • Switzerland (Schweiz)+41
  • Syria (‫سوريا‬‎)+963
  • Taiwan (台灣)+886
  • Tajikistan+992
  • Tanzania+255
  • Thailand (ไทย)+66
  • Timor-Leste+670
  • Togo+228
  • Tokelau+690
  • Tonga+676
  • Trinidad and Tobago+1868
  • Tunisia (‫تونس‬‎)+216
  • Turkey (Türkiye)+90
  • Turkmenistan+993
  • Turks and Caicos Islands+1649
  • Tuvalu+688
  • U.S. Virgin Islands+1340
  • Uganda+256
  • Ukraine (Україна)+380
  • United Arab Emirates (‫الإمارات العربية المتحدة‬‎)+971
  • United Kingdom+44
  • United States+1
  • Uruguay+598
  • Uzbekistan (Oʻzbekiston)+998
  • Vanuatu+678
  • Vatican City (Città del Vaticano)+39
  • Venezuela+58
  • Vietnam (Việt Nam)+84
  • Wallis and Futuna+681
  • Western Sahara (‫الصحراء الغربية‬‎)+212
  • Yemen (‫اليمن‬‎)+967
  • Zambia+260
  • Zimbabwe+263
  • Åland Islands+358
Thanks! We'll be in touch in the next 12 hours
Oops! Something went wrong while submitting the form.

Demystifying UI Frameworks and Theming for React Apps

Arnav Kasbi

Design Systems

Introduction:

In this blog, we will be talking about design systems, diving into the different types of CSS frameworks/libraries, then looking into issues that come with choosing a framework that is not right for your type of project. Then we will be going over different business use cases where these different frameworks/libraries match their requirements.

Let's paint a scenario: when starting a project, you start by choosing a JS framework. Let’s say, for example, that you went with a popular framework like React. Depending on whether you want an isomorphic app, you will look at Next.js. Next, we choose a UI framework, and that’s when our next set of problems appears.

WHICH ONE?

It’s hard to go with even the popular ones because it might not be what you are looking for. There are different types of libraries handling different types of use cases, and there are so many similar ones that each handle stuff slightly differently.

These frameworks come and go, so it’s essential to understand the fundamentals of CSS. These libraries and frameworks help you build faster; they don’t change how CSS works.

But, continuing with our scenario, let's say we choose a popular library like Bootstrap, or Material. Then, later on, as you’re working through the project, you notice issues like:

- Overriding default classes more than required 

- End up with ugly-looking code that’s hard to read

- Bloated CSS that reduces performance (flash of unstyled content issues, reduced CLS, FCP score)

- Swift changing designs, but you’re stuck with rigid frameworks, so migrating is hard and requires a lot more effort

- Require swift development but end up building from scratch

- Ending up with a div soup with no semantic meaning

To solve these problems and understand how these frameworks work, we have segregated them into the following category types. 

We will dig into each category and look at how they work, their pros/cons and their business use case.

Categorizing the available frameworks:

Vanilla Libraries 

These libraries allow you to write vanilla CSS with some added benefits like vendor prefixing, component-level scoping, etc.  You can use this as a building block to create your own styling methodology. Essentially, it’s mainly CSS in JS-type libraries that come in this type of category. CSS modules would also come under these as well since you are writing CSS in a module file.

Also, inline styles in React seem to resemble a css-in-js type method, but they are different. For inline styles, you would lose out on media queries, keyframe animations, and selectors like pseudo-class, pseudo-element, and attribute selectors. But css-in-js type libraries have these abilities.  

It also differs in how the out the CSS; inline styling would result in inline CSS in the HTML for that element, whereas css-in-js outputs as internal styles with class names.

Nowadays, these css-in-js types are popular for their optimized critical render path strategy for performance.

Example:

Emotion

import styled from @emotion/styled';
const Button = styled.button`
padding: 32px;
background-color: hotpink;
font-size: 24px;
border-radius: 4px;
color: black;
font-weight: bold;
&:hover {
color: white;
}
`
render(<Button>This my button component.</Button>)
view raw .ts hosted with ❤ by GitHub

Styled Components

const Button = styled.a`
/* This renders the buttons above... Edit me! */
display: inline-block;
border-radius: 3px;
padding: 0.5rem 0;
margin: 0.5rem 1rem;
width: 11rem;
background: transparent;
color: white;
border: 2px solid white;
/* The GitHub button is a primary button
* edit this to target it specifically! */
${props ⇒ props. primary && css`
background: white;
color: black;`}
view raw .ts hosted with ❤ by GitHub

List of example frameworks: 

   - Styled components

   - Emotion

   - Vanilla-extract

   - Stitches

   - CSS modules
(CSS modules is not an official spec or an implementation in the browser, but rather, it’s a process in a build step (with the help of Webpack or Browserify) that changes class names and selectors to be scoped.)

Pros:

  • Fully customizable—you can build on top of it
  • Doesn’t bloat CSS, only loads needed CSS
  • Performance
  • Little to no style collision

Cons:

  • Requires effort and time to make components from scratch
  • Danger of writing smelly code
  • Have to handle accessibility on your own

Where would you use these?

  • A website with an unconventional design that must be built from scratch.
  • Where performance and high webvital scores are required—the performance, in this case, refers to an optimized critical render path strategy that affects FCP and CLS.
  • Generally, it would be user-facing applications like B2C.

Unstyled / Functional Libraries

Before coming to the library, we would like to cover a bit on accessibility.

Apart from a website’s visual stuff, there is also a functional aspect, accessibility.

And many times, when we say accessibility in the context of web development, people automatically think of screen readers. But it doesn't just mean website accessibility to people with a disability; it also means enabling as many people as possible to use your websites, even people with or without disabilities or people who are limited. 

Different age groups

Font size settings on phones and browser settings should be reflected on the app

Situational limitation

Dark mode and light mode

Different devices

Mobile, desktop, tablet

Different screen sizes

Ultra wide 21:9, normal monitor screen size 16:9 

Interaction method

Websites can be accessible with keyboard only, mouse, touch, etc.

But these libraries mostly handle accessibility for the disabled, then interaction methods and focus management. The rest is left to developers, which includes settings that are more visual in nature, like screen sizes, light/dark mode etc.

In general, ARIA attributes and roles are used to provide information about the interaction of a complex widget. The libraries here sprinkle this information onto their components before giving them to be styled.

So, in short, these are low-level UI libraries that handle the functional part of the UI elements, like accessibility, keyboard navigation, or how they work. They come with little-to-no styling, which is meant to be overridden.

Radix UI

// Compose a Dialog with custom focus management
export const InfoDialog = ({ children }) => {
const dialogCloseButton = React.useRef(null);
return (
<Dialog.Root>
<Dialog.Trigger>View details</Dialog.Trigger>
<Dialog.Overlay />
<Dialog.Portal>
<DialogContent
onOpenAutoFocus={(event) => {
// Focus the close button when dialog opens
dialogCloseButton.current?.focus();
event.preventDefault();
}}>
{children}
<Dialog.Close ref={dialogCloseButton}>
Close
</Dialog.Close>
</DialogContent>
</Dialog.Portal>
</Dialog.Root>
)
}
view raw .ts hosted with ❤ by GitHub

React Aria

import React from "react";
function Breadcrumbs (props) {
let { navProps } = useBreadcrumbs(props);
let children = React. Children.toArray (props.children);
return (
<nav {...navProps}>
<ol style={{ display: 'flex', listStyle: 'none', margin: 0}}>
{children.map((child, i) => React.cloneElement(child, { isCurrent: i === children.le})
)}
</ol>
</nav>
)
}
view raw .ts hosted with ❤ by GitHub

List of the frameworks:

  • Radix UI
  • Reach UI
  • React Aria, React Stately (by Adobe)
  • Headless-UI

Pros:

  • Gives perfect accessibility and functionality
  • Gives the flexibility to create composable elements
  • Unopinionated styling, free to override

Cons:

  • Can’t be used for a rapid development project or prototyping
  • Have to understand the docs thoroughly to continue development at a normal pace

Where would you use these?

  • Websites like news or articles won’t require this.
  • Applications where accessibility is more important than styling and design (Government websites, banking, or even internal company apps).
  • Applications where importance is given to both accessibility and design, so customizability to these components is preferred (Teamflow, CodeSandbox, Vercel).
  • Can be paired with Vanilla libraries to provide performance with accessibility.
  • Can be paired with utility-style libraries to provide relatively faster development with accessibility.

Utility Styled Library / Framework

These types of libraries allow you to style your elements through their interfaces, either through class names or component props using composable individual CSS properties as per your requirements. The strongest point you have with such libraries is the flexibility of writing custom CSS properties. With these libraries, you would often require a “wrapper” class or components to be able to reuse them. 

These libraries dump these utility classes into your HTML, impacting your performance. Though there is still an option to improve the performance by purging the unused CSS from your project in a build step, even with that, the performance won’t be as good as css-in-js. The purging would look at the class names throughout the whole project and remove them if there is no reference. So, when loading a page, it would still load CSS that is not being used on the current page but another one.

Tailwind

const people = [
{
name: 'Calvin Hawkins',
email: 'calvin.hawkins@example.com',
image:
'https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
name: 'Kristen Ramos',
email: 'kristen.ramos@example.com',
image:
'https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
name: 'Ted Fox',
email: 'ted.fox@example.com',
image:
'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
]
export default function Example() {
return (
<ul className="divide-y divide-gray-200">
{people.map((person) => (
<li key={person.email} className="py-4 flex">
<img className="h-10 w-10 rounded-full" src={person.image} alt="" />
<div className="ml-3">
<p className="text-sm font-medium text-gray-900">{person.name}</p>
<p className="text-sm text-gray-500">{person.email}</p>
</div>
</li>
))}
</ul>
)
}
view raw .ts hosted with ❤ by GitHub

Chakra UI

import { MdStar } from "react-icons/md";
export default function Example() {
return (
<Center h="100vh">
<Box p="5" maxW="320px" borderWidth="1px">
<Image borderRadius="md" src="https://bit.ly/2k1H1t6" />
<Flex align="baseline" mt={2}>
<Badge colorScheme="pink">Plus</Badge>
<Text
ml={2}
textTransform="uppercase"
fontSize="sm"
fontWeight="bold"
color="pink.800"
>
Verified &bull; Cape Town
</Text>
</Flex>
<Text mt={2} fontSize="xl" fontWeight="semibold" lineHeight="short">
Modern, Chic Penthouse with Mountain, City & Sea Views
</Text>
<Text mt={2}>$119/night</Text>
<Flex mt={2} align="center">
<Box as={MdStar} color="orange.400" />
<Text ml={1} fontSize="sm">
<b>4.84</b> (190)
</Text>
</Flex>
</Box>
</Center>
);
}
view raw .ts hosted with ❤ by GitHub

List of the frameworks

  • Tailwind
  • Chakra UI (although it has some prebuilt components, its concept is driven from Tailwind)
  • Tachyons
  • xStyled

Pros:

  • Rapid development and prototyping
  • Gives flexibility to styling
  • Enforces a little consistency; you don’t have to use magic numbers while creating the layout (spacing values, responsive variables like xs, sm, etc.)
  • Less context switching—you’ll write CSS in your HTML elements

Cons:

  • Endup with ugly-looking/hard-to-read code
  • Lack of importance to components, you would have to handle accessibility yourself
  • Creates a global stylesheet that would have unused classes

Where would you use these?

  • Easier composition of simpler components to build large applications.
  • Modular applications where rapid customization is required, like font sizes, color pallets, themes, etc.
  • FinTech or healthcare applications where you need features like theme-based toggling in light/dark mode to be already present.
  • Application where responsive design is supported out of the box, along with ease of accessibility and custom breakpoints for responsiveness.

Pre-styled / All-In-One Framework 

These are popular frameworks that come with pre-styled, ready-to-use components out of the box with little customization.

These are heavy libraries that have fixed styling that can be overridden. However, generally speaking, overriding the classes would just load in extra CSS, which just clogs up the performance. These kinds of libraries are generally more useful for rapid prototyping and not in places with heavy customization and priority on performance.

These are quite beginner friendly as well, but if you are a beginner, it is best to understand the basics and fundamentals of CSS rather than fully relying on frameworks like these as your crutches. Although, these frameworks have their pros with speed of development.

Material UI

<Box
component="form"
className="lgn-form-content"
id="loginForm"
onSubmit={formik.handleSubmit}
>
<Input
id="activationCode"
placeholder="Enter 6 Digit Auth Code"
className="lgn-form-input"
type="text"
onChange={formik.handleChange}
value={formik.values.activationCode}
/>
<Button
sx={{ marginBottom: "24px", marginTop: "1rem" }}
type="submit"
className="lgn-form-submit"
form="loginForm"
onKeyUp={(e) =>
keyUpHandler(e, formik.handleSubmit, formik.isSubmitting)
}
>
<Typography className="lgn-form-submit-text">
Activate & Sign In
</Typography>
</Button>
{formik.errors.activationCode && formik.touched.activationCode ? (
<Typography color="white">{formik.errors.activationCode}</Typography>
) : null}
</Box>
view raw .ts hosted with ❤ by GitHub

BootStrap

<Accordion isExpanded={true} useArrow={true}>
<AccordionLabel className="editor-accordion-label">RULES</AccordionLabel>
<AccordionSection>
<div className="editor-detail-panel editor-detail-panel-column">
<div className="label">Define conditional by adding a rule</div>
<div className="rule-actions"></div>
</div>
</AccordionSection>
</Accordion>
view raw .ts hosted with ❤ by GitHub

List of the framework:

  • Bootstrap
  • Semantic UI
  • Material UI
  • Bulma
  • Mantine 

Pros: 

  • Faster development, saves time since everything comes out of the box.
  • Helps avoid cross-browser bugs
  • Helps follow best practices (accessibility)

Cons:

  • Low customization
  • Have to become familiar with the framework and its nuisance
  • Bloated CSS, since its loading in everything from the framework on top of overridden styles

Where would you use these?

  • Focus is not on nitty-gritty design but on development speed and functionality.
  • Enterprise apps where the UI structure of the application isn’t dynamic and doesn’t get altered a lot.
  • B2B apps mostly where the focus is on getting the functionality out fast—UX is mostly driven by ease of use of the functionality with a consistent UI design.
  • Applications where you want to focus more on cross-browser compatibility.

Conclusion:

This is not a hard and fast rule; there are still a bunch of parameters that aren’t covered in this blog, like developer preference, or legacy code that already uses a pre-existing framework. So, pick one that seems right for you, considering the parameters in and outside this blog and your judgment.

To summarize a little on the pros and cons of the above categories, here is a TLDR diagram:

Pictorial Representation of the Summary

Get the latest engineering blogs delivered straight to your inbox.
No spam. Only expert insights.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings

You may also like

No items found.

Demystifying UI Frameworks and Theming for React Apps

Introduction:

In this blog, we will be talking about design systems, diving into the different types of CSS frameworks/libraries, then looking into issues that come with choosing a framework that is not right for your type of project. Then we will be going over different business use cases where these different frameworks/libraries match their requirements.

Let's paint a scenario: when starting a project, you start by choosing a JS framework. Let’s say, for example, that you went with a popular framework like React. Depending on whether you want an isomorphic app, you will look at Next.js. Next, we choose a UI framework, and that’s when our next set of problems appears.

WHICH ONE?

It’s hard to go with even the popular ones because it might not be what you are looking for. There are different types of libraries handling different types of use cases, and there are so many similar ones that each handle stuff slightly differently.

These frameworks come and go, so it’s essential to understand the fundamentals of CSS. These libraries and frameworks help you build faster; they don’t change how CSS works.

But, continuing with our scenario, let's say we choose a popular library like Bootstrap, or Material. Then, later on, as you’re working through the project, you notice issues like:

- Overriding default classes more than required 

- End up with ugly-looking code that’s hard to read

- Bloated CSS that reduces performance (flash of unstyled content issues, reduced CLS, FCP score)

- Swift changing designs, but you’re stuck with rigid frameworks, so migrating is hard and requires a lot more effort

- Require swift development but end up building from scratch

- Ending up with a div soup with no semantic meaning

To solve these problems and understand how these frameworks work, we have segregated them into the following category types. 

We will dig into each category and look at how they work, their pros/cons and their business use case.

Categorizing the available frameworks:

Vanilla Libraries 

These libraries allow you to write vanilla CSS with some added benefits like vendor prefixing, component-level scoping, etc.  You can use this as a building block to create your own styling methodology. Essentially, it’s mainly CSS in JS-type libraries that come in this type of category. CSS modules would also come under these as well since you are writing CSS in a module file.

Also, inline styles in React seem to resemble a css-in-js type method, but they are different. For inline styles, you would lose out on media queries, keyframe animations, and selectors like pseudo-class, pseudo-element, and attribute selectors. But css-in-js type libraries have these abilities.  

It also differs in how the out the CSS; inline styling would result in inline CSS in the HTML for that element, whereas css-in-js outputs as internal styles with class names.

Nowadays, these css-in-js types are popular for their optimized critical render path strategy for performance.

Example:

Emotion

import styled from @emotion/styled';
const Button = styled.button`
padding: 32px;
background-color: hotpink;
font-size: 24px;
border-radius: 4px;
color: black;
font-weight: bold;
&:hover {
color: white;
}
`
render(<Button>This my button component.</Button>)
view raw .ts hosted with ❤ by GitHub

Styled Components

const Button = styled.a`
/* This renders the buttons above... Edit me! */
display: inline-block;
border-radius: 3px;
padding: 0.5rem 0;
margin: 0.5rem 1rem;
width: 11rem;
background: transparent;
color: white;
border: 2px solid white;
/* The GitHub button is a primary button
* edit this to target it specifically! */
${props ⇒ props. primary && css`
background: white;
color: black;`}
view raw .ts hosted with ❤ by GitHub

List of example frameworks: 

   - Styled components

   - Emotion

   - Vanilla-extract

   - Stitches

   - CSS modules
(CSS modules is not an official spec or an implementation in the browser, but rather, it’s a process in a build step (with the help of Webpack or Browserify) that changes class names and selectors to be scoped.)

Pros:

  • Fully customizable—you can build on top of it
  • Doesn’t bloat CSS, only loads needed CSS
  • Performance
  • Little to no style collision

Cons:

  • Requires effort and time to make components from scratch
  • Danger of writing smelly code
  • Have to handle accessibility on your own

Where would you use these?

  • A website with an unconventional design that must be built from scratch.
  • Where performance and high webvital scores are required—the performance, in this case, refers to an optimized critical render path strategy that affects FCP and CLS.
  • Generally, it would be user-facing applications like B2C.

Unstyled / Functional Libraries

Before coming to the library, we would like to cover a bit on accessibility.

Apart from a website’s visual stuff, there is also a functional aspect, accessibility.

And many times, when we say accessibility in the context of web development, people automatically think of screen readers. But it doesn't just mean website accessibility to people with a disability; it also means enabling as many people as possible to use your websites, even people with or without disabilities or people who are limited. 

Different age groups

Font size settings on phones and browser settings should be reflected on the app

Situational limitation

Dark mode and light mode

Different devices

Mobile, desktop, tablet

Different screen sizes

Ultra wide 21:9, normal monitor screen size 16:9 

Interaction method

Websites can be accessible with keyboard only, mouse, touch, etc.

But these libraries mostly handle accessibility for the disabled, then interaction methods and focus management. The rest is left to developers, which includes settings that are more visual in nature, like screen sizes, light/dark mode etc.

In general, ARIA attributes and roles are used to provide information about the interaction of a complex widget. The libraries here sprinkle this information onto their components before giving them to be styled.

So, in short, these are low-level UI libraries that handle the functional part of the UI elements, like accessibility, keyboard navigation, or how they work. They come with little-to-no styling, which is meant to be overridden.

Radix UI

// Compose a Dialog with custom focus management
export const InfoDialog = ({ children }) => {
const dialogCloseButton = React.useRef(null);
return (
<Dialog.Root>
<Dialog.Trigger>View details</Dialog.Trigger>
<Dialog.Overlay />
<Dialog.Portal>
<DialogContent
onOpenAutoFocus={(event) => {
// Focus the close button when dialog opens
dialogCloseButton.current?.focus();
event.preventDefault();
}}>
{children}
<Dialog.Close ref={dialogCloseButton}>
Close
</Dialog.Close>
</DialogContent>
</Dialog.Portal>
</Dialog.Root>
)
}
view raw .ts hosted with ❤ by GitHub

React Aria

import React from "react";
function Breadcrumbs (props) {
let { navProps } = useBreadcrumbs(props);
let children = React. Children.toArray (props.children);
return (
<nav {...navProps}>
<ol style={{ display: 'flex', listStyle: 'none', margin: 0}}>
{children.map((child, i) => React.cloneElement(child, { isCurrent: i === children.le})
)}
</ol>
</nav>
)
}
view raw .ts hosted with ❤ by GitHub

List of the frameworks:

  • Radix UI
  • Reach UI
  • React Aria, React Stately (by Adobe)
  • Headless-UI

Pros:

  • Gives perfect accessibility and functionality
  • Gives the flexibility to create composable elements
  • Unopinionated styling, free to override

Cons:

  • Can’t be used for a rapid development project or prototyping
  • Have to understand the docs thoroughly to continue development at a normal pace

Where would you use these?

  • Websites like news or articles won’t require this.
  • Applications where accessibility is more important than styling and design (Government websites, banking, or even internal company apps).
  • Applications where importance is given to both accessibility and design, so customizability to these components is preferred (Teamflow, CodeSandbox, Vercel).
  • Can be paired with Vanilla libraries to provide performance with accessibility.
  • Can be paired with utility-style libraries to provide relatively faster development with accessibility.

Utility Styled Library / Framework

These types of libraries allow you to style your elements through their interfaces, either through class names or component props using composable individual CSS properties as per your requirements. The strongest point you have with such libraries is the flexibility of writing custom CSS properties. With these libraries, you would often require a “wrapper” class or components to be able to reuse them. 

These libraries dump these utility classes into your HTML, impacting your performance. Though there is still an option to improve the performance by purging the unused CSS from your project in a build step, even with that, the performance won’t be as good as css-in-js. The purging would look at the class names throughout the whole project and remove them if there is no reference. So, when loading a page, it would still load CSS that is not being used on the current page but another one.

Tailwind

const people = [
{
name: 'Calvin Hawkins',
email: 'calvin.hawkins@example.com',
image:
'https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
name: 'Kristen Ramos',
email: 'kristen.ramos@example.com',
image:
'https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
name: 'Ted Fox',
email: 'ted.fox@example.com',
image:
'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
]
export default function Example() {
return (
<ul className="divide-y divide-gray-200">
{people.map((person) => (
<li key={person.email} className="py-4 flex">
<img className="h-10 w-10 rounded-full" src={person.image} alt="" />
<div className="ml-3">
<p className="text-sm font-medium text-gray-900">{person.name}</p>
<p className="text-sm text-gray-500">{person.email}</p>
</div>
</li>
))}
</ul>
)
}
view raw .ts hosted with ❤ by GitHub

Chakra UI

import { MdStar } from "react-icons/md";
export default function Example() {
return (
<Center h="100vh">
<Box p="5" maxW="320px" borderWidth="1px">
<Image borderRadius="md" src="https://bit.ly/2k1H1t6" />
<Flex align="baseline" mt={2}>
<Badge colorScheme="pink">Plus</Badge>
<Text
ml={2}
textTransform="uppercase"
fontSize="sm"
fontWeight="bold"
color="pink.800"
>
Verified &bull; Cape Town
</Text>
</Flex>
<Text mt={2} fontSize="xl" fontWeight="semibold" lineHeight="short">
Modern, Chic Penthouse with Mountain, City & Sea Views
</Text>
<Text mt={2}>$119/night</Text>
<Flex mt={2} align="center">
<Box as={MdStar} color="orange.400" />
<Text ml={1} fontSize="sm">
<b>4.84</b> (190)
</Text>
</Flex>
</Box>
</Center>
);
}
view raw .ts hosted with ❤ by GitHub

List of the frameworks

  • Tailwind
  • Chakra UI (although it has some prebuilt components, its concept is driven from Tailwind)
  • Tachyons
  • xStyled

Pros:

  • Rapid development and prototyping
  • Gives flexibility to styling
  • Enforces a little consistency; you don’t have to use magic numbers while creating the layout (spacing values, responsive variables like xs, sm, etc.)
  • Less context switching—you’ll write CSS in your HTML elements

Cons:

  • Endup with ugly-looking/hard-to-read code
  • Lack of importance to components, you would have to handle accessibility yourself
  • Creates a global stylesheet that would have unused classes

Where would you use these?

  • Easier composition of simpler components to build large applications.
  • Modular applications where rapid customization is required, like font sizes, color pallets, themes, etc.
  • FinTech or healthcare applications where you need features like theme-based toggling in light/dark mode to be already present.
  • Application where responsive design is supported out of the box, along with ease of accessibility and custom breakpoints for responsiveness.

Pre-styled / All-In-One Framework 

These are popular frameworks that come with pre-styled, ready-to-use components out of the box with little customization.

These are heavy libraries that have fixed styling that can be overridden. However, generally speaking, overriding the classes would just load in extra CSS, which just clogs up the performance. These kinds of libraries are generally more useful for rapid prototyping and not in places with heavy customization and priority on performance.

These are quite beginner friendly as well, but if you are a beginner, it is best to understand the basics and fundamentals of CSS rather than fully relying on frameworks like these as your crutches. Although, these frameworks have their pros with speed of development.

Material UI

<Box
component="form"
className="lgn-form-content"
id="loginForm"
onSubmit={formik.handleSubmit}
>
<Input
id="activationCode"
placeholder="Enter 6 Digit Auth Code"
className="lgn-form-input"
type="text"
onChange={formik.handleChange}
value={formik.values.activationCode}
/>
<Button
sx={{ marginBottom: "24px", marginTop: "1rem" }}
type="submit"
className="lgn-form-submit"
form="loginForm"
onKeyUp={(e) =>
keyUpHandler(e, formik.handleSubmit, formik.isSubmitting)
}
>
<Typography className="lgn-form-submit-text">
Activate & Sign In
</Typography>
</Button>
{formik.errors.activationCode && formik.touched.activationCode ? (
<Typography color="white">{formik.errors.activationCode}</Typography>
) : null}
</Box>
view raw .ts hosted with ❤ by GitHub

BootStrap

<Accordion isExpanded={true} useArrow={true}>
<AccordionLabel className="editor-accordion-label">RULES</AccordionLabel>
<AccordionSection>
<div className="editor-detail-panel editor-detail-panel-column">
<div className="label">Define conditional by adding a rule</div>
<div className="rule-actions"></div>
</div>
</AccordionSection>
</Accordion>
view raw .ts hosted with ❤ by GitHub

List of the framework:

  • Bootstrap
  • Semantic UI
  • Material UI
  • Bulma
  • Mantine 

Pros: 

  • Faster development, saves time since everything comes out of the box.
  • Helps avoid cross-browser bugs
  • Helps follow best practices (accessibility)

Cons:

  • Low customization
  • Have to become familiar with the framework and its nuisance
  • Bloated CSS, since its loading in everything from the framework on top of overridden styles

Where would you use these?

  • Focus is not on nitty-gritty design but on development speed and functionality.
  • Enterprise apps where the UI structure of the application isn’t dynamic and doesn’t get altered a lot.
  • B2B apps mostly where the focus is on getting the functionality out fast—UX is mostly driven by ease of use of the functionality with a consistent UI design.
  • Applications where you want to focus more on cross-browser compatibility.

Conclusion:

This is not a hard and fast rule; there are still a bunch of parameters that aren’t covered in this blog, like developer preference, or legacy code that already uses a pre-existing framework. So, pick one that seems right for you, considering the parameters in and outside this blog and your judgment.

To summarize a little on the pros and cons of the above categories, here is a TLDR diagram:

Pictorial Representation of the Summary

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings