Mastering the Design-to-Code Flow with Figma, Storybook, and Angular (Part 4)
Table of Contents
Welcome back to our design token series! In our previous entries, we’ve explored the concept of extracting design tokens from Figma. Today, we talk about applying the design tokens by creating Angular components.
Applying Design Tokens
In the last blog post, we ended with SCSS files containing variables. To apply this variables, we map this variables to the SCSS files of the created components. Having a nicely structured SCSS allows to switch between styles/variants without requiring any adaption of the component.
This means, with a smart conversion we retrieve a SCSS file as follows
and can apply this SCSS inside the Angular component as follows
Performance Considerations
Performance considerations are crucial when developing components for modern web applications. Understanding and optimizing the amount of Document Object Model (DOM) elements and the usage of CSS selectors can significantly impact the performance and user experience of your application.
Amount of DOM
The DOM represents the page structure, and each element is a node in this tree-like structure. A large DOM can slow down your application because more nodes mean more work for the browser to layout, render, and repaint as users interact with the page. Here are some strategies to consider:
Simplify Your Structure: Use fewer, more semantic HTML elements. Aim for a cleaner, more efficient structure that accomplishes the same result.
Remove Non-Essential Elements: Analyze your DOM and remove any elements that don’t contribute to the user experience or could be replaced with more efficient CSS.
Virtualize Long Lists: If you have long lists or tables, consider using a virtualization library to only render items in view. For example, I can highly recommend Virtual Scrolling from RxAngular.
Usage of CSS Selectors
CSS selectors are a powerful way to apply styles to your elements, but they can also become a performance bottleneck if not used wisely. Complex selectors force the browser to do more work to determine which elements should receive the styles. We highly recommend to study the presentation by Nolan Lawson which covers many important aspects of CSS performance. In the following I provide a list of what I usually try to follow:
Avoid Universal Selectors: Universal selectors (
) are often overkill and can lead to performance issues, especially in complex documents. They force the browser to consider every element as a potential match.*
Minimize Depth: Deeply nested selectors can be inefficient. Each additional level adds to the time it takes for the browser to evaluate and apply styles. Aim for shallow, concise selectors.
Rightmost Selector: The rightmost selector, also known as the “key selector,” is the most critical part of your query. Browsers filter the DOM based on this, so ensuring it’s as specific as possible can greatly reduce the initial filtering scope.
Avoid Attribute Value Selectors and Certain Pseudo-Classes: Attribute selectors (e.g.,
) and pseudo-classes like[type="text"]
or:nth-child
can be less efficient because they often lack specific browser optimizations. These selectors require the browser to perform more complex calculations, leading to potential performance bottlenecks, especially in large documents or dynamic applications. Instead, use class selectors or IDs whenever possible to provide direct and fast access to elements.:not
Leverage Shadow DOM for Style Encapsulation and Optimization: Utilizing Shadow DOM in web components can greatly enhance performance and maintainability. Shadow DOM allows for style encapsulation, meaning styles defined inside a shadow tree won’t affect the main document and vice versa. This scoping reduces the complexity of style calculations and re-calculations when elements update.
Implement CSS Containment: Use the
property in CSS to indicate that an element's content is independent from the rest of the document. This allows the browser to optimize rendering by not considering changes within the contained element when calculating layout, style, paint, or size for the rest of the document.contain
Utilize Content Visibility for Further Optimization: Alongside CSS containment, consider using the
property. This property enables the browser to skip the rendering work for off-screen content until it's needed. This can significantly reduce the initial load time and resource usage on long web pages.content-visibility
Extendable Components
Angular’s powerful framework provides an array of tools and features enabling developers to build scalable, reusable, and maintainable components. Understanding how to leverage these features is key to creating extendable components that can adapt to various contexts and requirements. This section delves into several Angular concepts, including ng-content
ng-template
ng-container
ng-content
At the heart of creating extendable components is ng-content
select
ng-content
ContentChild and ViewChild
@ContentChild
@ViewChild
@ContentChild
ng-content
@ViewChild
ng-template and ngTemplateOutlet
ng-template
ngTemplateOutlet
ng-template
ng-container
ng-container
In Angular, creating dynamic and responsive components often requires direct interaction with the component’s template and the DOM. ViewContainerRef
TemplateRef
ElementRef
ViewContainerRef
TemplateRef
ViewContainerRef
ElementRef
Retrieving your right Ref: In Angular, when you’re querying for elements or directives using ViewChild
ContentChild
static: true: Setting
ensures the element is available instatic: true
. It's suitable for elements that are present in the template and don't rely on binding resolution or external conditions.ngOnInit
read: The
option allows you to specify what to return from the queried element. For instance, you can readread
,ElementRef
, or any directive instance from the queried element.ViewContainerRef
Example: Let’s see how you might use ViewContainerRef
TemplateRef
Define your
in the template:TemplateRef
2. Access and manipulate the template in your component:
In this example, we’re defining a template in the HTML with ng-template
ViewChild
TemplateRef
ViewContainerRef
createEmbeddedView
ViewContainerRef
Type Checking
Type checking is an essential aspect of building robust Angular applications, ensuring that your components and templates interact as expected. When you’re working with ng-template
any
ngTemplateContextGuard
Conclusion
In this deep dive into Angular’s powerful features for creating extendable components, we’ve explored a range of tools and concepts that are essential for any advanced Angular developer.
Understanding how to create extendable components is just one part of the equation. The next step in ensuring the quality and reliability of your Angular applications is effective testing. In the next part of the series, we’ll delve into testing Angular components (with Storybook).