Tutorials on Css

Learn about Css from fellow newline community members!

  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL
  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL

How To Make CSS “Click” Through Mastering Layouts

CSS is and always has been a unique challenge. It's a tool that often divides developers into two camps: those who love it and those who kinda hate it. CSS can be an enigma even to the most skilled of devs. Developers able to create amazing pieces of code in Python and Node can be at a loss when learning how to buld CSS layouts. Why is CSS, a cornerstone of web development, often perceived as more daunting than other programming languages? It's a question that leads to a deeper exploration of this language's peculiar nature. In this article, you will discover: By the end of this guide, you'll gain a new perspective on CSS, understanding not only its challenges but also how to conquer them, elevating your front-end development skills to new heights. Let's unravel the mystique of CSS and embark on a journey to mastery. The CSS Conundrum: Easy to Learn, Hard to Master CSS, or Cascading Style Sheets, is often seen as the great paradox in the toolkit of a software engineer. On the surface, it appears deceptively simple - a language made for styling web pages. Yet, beneath this facade lies a complex system that can baffle even the most experienced developers. The Deceptive Simplicity of CSS For many developers, their first encounter with CSS is marked by a sense of quick achievement. Changing colors, adjusting fonts, and setting backgrounds feel straightforward and instantly rewarding. This initial ease creates an illusion of simplicity, but as one delves deeper, the real challenges of CSS emerge. Why CSS Feels More Challenging Than Other Languages The Journey to Mastery Mastering CSS requires more than just understanding its properties and syntax. It demands a deep comprehension of how browsers interpret CSS, a keen eye for design, and an adaptive mindset to tackle the fluid nature of web layouts. This journey from basic knowledge to mastery involves: Common Roadblocks in CSS Mastery Mastering CSS is a journey filled with unique challenges, even for experienced developers. While transitioning from basic to advanced CSS, several roadblocks often stand in the way, making the process seem daunting and sometimes frustrating. 1. Overcoming the Initial Learning Curve The initial ease of CSS can lead to a false sense of mastery. As developers delve deeper, they encounter more complex scenarios that aren't as straightforward as changing a background color or aligning text. This shift from simple styling to intricate layout design often marks the first significant hurdle. 2. The Box Model Confusion One of the fundamental concepts in CSS, the box model, can be a source of confusion. Understanding how margins, borders, padding, and content areas interact and affect the overall layout is crucial. Misunderstanding this model can lead to unexpected layout behaviors and design flaws. 3. Responsive Design Challenges Responsive design is a critical aspect of modern web development, but mastering it requires a nuanced understanding of various devices and screen sizes. Developers often struggle to create designs that are flexible and maintain visual integrity across different environments. 4. Mastery of Positioning and Flexbox/Grid Positioning elements on a page using traditional methods, Flexbox, or CSS Grid, comes with its challenges. Developers must understand the strengths and limitations of each approach to create effective layouts. Overreliance on Flexbox or Grid without understanding the underlying principles can lead to rigid and unimaginative designs. 5. Cross-Browser Compatibility Issues Different browsers can interpret CSS in varying ways, leading to inconsistencies in how a webpage is rendered. Navigating these differences and ensuring a consistent experience across all browsers is a common stumbling block. 6. Keeping Up with Evolving Standards CSS is continually evolving, with new properties and features being added regularly. Staying updated with these changes and understanding how to implement them effectively can be overwhelming. 7. Balancing Aesthetics with Functionality Lastly, CSS is unique in that it requires a blend of technical skills and design sensibility. Striking the right balance between creating a visually appealing layout and ensuring it functions well can be challenging, especially for those more inclined towards programming than design. Flexbox and Grid: Tools, Not Solutions In the realm of CSS, Flexbox and Grid are often hailed as the saviors of layout design, especially among software engineers who find comfort in their apparent simplicity and power. However, it's crucial to understand that these are tools, not complete solutions, for mastering CSS layouts. Understanding Flexbox and Grid as Part of a Larger System Flexbox and Grid offer fantastic capabilities in arranging elements on a web page, but they work best when used as part of a broader CSS strategy. Relying solely on these tools without a solid foundation in basic CSS principles can lead to layouts that are technically functional but lack the finesse and adaptability of a well-rounded approach. The Pitfalls of Overreliance Many developers fall into the trap of overrelying on Flexbox and Grid. This overdependence can mask underlying gaps in understanding how CSS works as a whole. For example, without a proper grasp of the box model or positioning, a layout might work in some scenarios but break in others, especially when it comes to responsive design. Flexbox and Grid in the Real World In practical terms, Flexbox is excellent for one-dimensional layouts – think along the lines of rows or columns. Grid, on the other hand, shines in two-dimensional layouts, where control over both rows and columns is required. However, the true art lies in knowing when to use which tool and how to combine them effectively with other CSS properties. Beyond Tools: Embracing the Fundamentals The key to truly mastering CSS layouts is to go beyond these tools. It involves understanding the core principles of CSS – from the cascade and specificity to inheritance and the stacking context. These fundamentals form the backbone of any complex layout design, with Flexbox and Grid serving as powerful allies rather than all-in-one solutions. Balancing Creativity with Technical Know-How Ultimately, the mastery of CSS layouts is about balancing technical skill with creative problem-solving. Flexbox and Grid are parts of this equation, but they don't replace the need for a deep, intuitive understanding of CSS as a whole. This balance is what separates competent engineers from truly exceptional ones. Mastering Design Patterns in CSS Design patterns in CSS are essential for creating complex and responsive layouts. They provide a systematic approach to dealing with common problems in web design, making it easier to develop scalable and maintainable code. For software engineers, understanding and mastering these patterns is crucial for efficient and effective CSS coding. 1. The Importance of CSS Design Patterns Design patterns in CSS are not just about making your code look organized; they are about making it work efficiently in a wide range of scenarios. These patterns help in creating a consistent look and feel across different web pages and applications, which is essential for user experience and brand consistency. 2. Implementing Design Patterns in Projects Implementing these design patterns requires a deep understanding of CSS properties and how they interact with HTML elements. This includes knowing how to use Flexbox and Grid to create responsive layouts and how to apply the Box Model for spacing and alignment. 3. Design Patterns and Responsive Web Design Responsive web design is a critical aspect of modern web development. CSS design patterns play a significant role in making websites responsive. By using these patterns, developers can ensure that their websites look great on all devices, from desktops to smartphones. 4. Learning and Practicing Design Patterns Mastering CSS design patterns requires a deep understanding of what’s going on behind the scenes of the layout, exposure to multiple real-world scenarios and seeing how these patterns apply to it, and, of course, practice. You can learn how to use every design pattern, implement them with both Flexbox and CSS Grid, see examples of real landing pages and sharpen your skills with short and fun exercises inside of “Mastering CSS Layout”. 5. Advanced Techniques and Best Practices As you become more comfortable with basic design patterns, you can explore advanced techniques like animations, transitions, and transformations. Keeping up with the latest best practices in CSS design will also help in creating more efficient and visually appealing layouts. Building Intuitive Understanding of CSS Layouts For many software engineers, especially those accustomed to more logical and procedural programming languages, developing an intuitive understanding of CSS layouts can be challenging. However, achieving this level of proficiency is key to mastering CSS and creating effective, responsive web designs. 1. Understanding the Language of CSS CSS is more than a list of rules; it's a language with its own logic and nuances. To develop an intuitive understanding, you need to immerse yourself in the language of CSS. This involves not just learning properties and syntax but understanding how CSS 'thinks'—how it interprets and applies styles to HTML elements. 2. The Visual Aspect of CSS Unlike many programming languages that are logic and text-based, CSS is inherently visual. Developing an intuitive understanding of CSS means being able to visualize how styles will render on a page. This skill is honed through practice, experimentation, and frequently viewing the real-time impact of your CSS changes. 3. Pattern Recognition in Layout Design An essential part of building intuition in CSS is learning to recognize and implement common layout patterns. Understanding these patterns helps in quickly determining the best approach for a layout, whether it's a flexbox for a one-dimensional design or a grid for more complex two-dimensional layouts. 4. Debugging and Experimentation Debugging is an invaluable skill for developing CSS intuition. By troubleshooting layout issues, you learn to anticipate how changes in one part of your CSS can affect the rest of your layout. Experimentation, too, plays a crucial role. Trying out different approaches and seeing their effects helps build a mental model of how CSS works. 5. Learning from Real-World Examples Analyzing the CSS of well-designed websites is an excellent way to develop intuition. Tools like browser developer tools allow you to see how different CSS properties are being used in real-world applications. This practice can provide insights into effective layout strategies and techniques. 6. Continuous Practice and Updation Finally, building an intuitive understanding of CSS layouts requires continuous practice and keeping up with the latest developments in CSS. Regularly working on diverse web projects and staying informed about new CSS features and best practices will deepen your intuitive grasp of the language. Case Studies: From Theory to Practice Understanding CSS theory is one thing; applying it in real-world scenarios is another. In this section, we delve into case studies that demonstrate how the mastery of CSS design patterns, Flexbox, and Grid can transform complex layout challenges into successful, responsive web designs. 1. Case Study: E-Commerce Website Overhaul The challenge: A popular e-commerce site faced issues with inconsistent layouts and poor responsiveness across devices. Solution: By implementing a combination of CSS Grid for the overall layout structure and Flexbox for individual components, the website achieved a fluid and adaptable design. The use of CSS variables and media queries further enhanced the responsiveness and maintainability of the site. 2. Case Study: Tech Blog Redesign The challenge: A tech blog required a modern, visually appealing, and mobile-friendly redesign. Solution: The redesign focused on a card layout using Flexbox, improving content organization and readability. Media queries ensured the layout adapted beautifully across various screen sizes, enhancing the user experience for mobile readers. 3. Case Study: Corporate Website Accessibility Improvement The challenge: A corporate website needed to improve its accessibility and SEO without compromising on design aesthetics. Solution: The developers employed semantic HTML and CSS best practices, including a Grid-based layout for main sections and Flexbox for navigation. This approach improved site accessibility and SEO while maintaining a sophisticated look. 4. Case Study: Responsive Multi-Page Application The challenge: A multi-page application required a cohesive and responsive design to provide a seamless user experience. Solution: The application used CSS Grid for defining the main layout grids, with Flexbox managing content alignment and distribution within these grids. This combination, along with strategic use of breakpoints, ensured a consistent and responsive experience across all pages. 5. Case Study: Online Portfolio with Dynamic Elements The challenge: An artist’s online portfolio needed to showcase work dynamically and engagingly. Solution: The portfolio leveraged CSS animations and transitions within a Flexbox layout to create engaging, interactive elements. CSS custom properties were used for theming, allowing for easy updates and variations. Next Steps: Enhancing Your CSS Skills After delving into the intricacies of CSS through the 'Mastering CSS Layouts' course or similar learning experiences, the next step is to continue honing these skills. Enhancing your CSS expertise is a continuous process, crucial for staying relevant and innovative in the ever-evolving field of web development. 1. Implementing New Knowledge in Projects Start applying your new CSS skills in real-world projects. Whether it's refining existing work or starting new projects, use this opportunity to put theory into practice. Experiment with different layouts, and don’t hesitate to push the boundaries of your comfort zone. 2. Building a Portfolio of Diverse Projects Develop a portfolio showcasing a variety of CSS techniques. Include projects that demonstrate your proficiency in responsive design, Flexbox and Grid usage, and creative layout solutions. This portfolio will not only serve as a testament to your skills but also as a reference for future projects. 3. Staying Updated with CSS Trends The world of CSS is dynamic, with new properties, techniques, and best practices emerging regularly. Stay informed about the latest developments by following industry blogs, participating in web development forums, and attending relevant webinars or conferences. 4. Exploring Advanced CSS Concepts Dive deeper into advanced CSS concepts such as animations, transitions, and CSS preprocessors like SASS or LESS. These skills can add another layer of sophistication to your web designs and improve your workflow. 5. Contributing to Open Source and Community Projects Engage with the developer community by contributing to open-source projects. This not only helps in refining your skills but also provides exposure to diverse coding styles and project requirements. 6. Continuous Learning and Experimentation Never stop learning and experimenting. Whether through formal courses, self-taught challenges, or collaborative projects, continuous learning is key to staying proficient and creative in CSS. 7. Seeking Feedback and Collaborative Opportunities Actively seek feedback on your work from peers and mentors. Collaboration can bring new perspectives and ideas, helping you grow as a developer. Participating in coding challenges or hackathons can also be an excellent way to test your skills under different constraints and requirements. Conclusion Embarking on the journey to master CSS layouts is more than just enhancing a technical skillset; it's about embracing a new perspective on how web interfaces are created and interacted with. Throughout this article, we've explored the intricate world of CSS, from its deceptive simplicity to the mastery of complex design patterns and the integration of tools like Flexbox and Grid. We've covered: As we conclude, remember that mastering CSS layouts is a continuous journey, one that requires persistence, creativity, and an eagerness to experiment and learn. The skills you've developed and the insights you've gained will serve as a strong foundation for your future projects, enabling you to craft web experiences that are not only functional but also visually compelling and user-friendly. Thank you for joining me in this deep dive into the world of CSS. May your journey in web development be ever-evolving, filled with learning, innovation, and the creation of exceptional web experiences.

Announcing "Mastering CSS Layout": The Only Guide You Need To Build Any Layout You Want

If you’ve ever thought to yourself “man, CSS sucks !” when trying to build a layout, we have great news for you. We’re here to help you say goodbye to the frustration and confusion that often goes hand in hand with the little devil we like to call CSS. Introducing "Mastering CSS Layout" - the guide that promises to help you… uh… master CSS layout. Refreshingly intuitive title, if you ask me. "Mastering CSS Layout" is not just another course on CSS Grid or Flexbox. We’re taking a step back and covering the fundamental Design Patterns that are the building blocks of every CSS layout. From simple to complex. Abstract to highly structured layouts. And you can use them with both Flexbox and CSS Grid. Understanding these patterns is the key to unlocking your potential to design web layouts with confidence and creativity. Here's a sneak peek at what "Mastering CSS Layout" offers: Many new and even intermediate developers find building CSS layouts hard, confusing and often nonsensical, despite being comfortable with languages like JavaScript or even Python. This guide addresses the root cause of this challenge by focusing on understanding the underlying design patterns rather than getting bogged down with decisions like choosing between Flexbox or CSS Grid, or selecting a CSS framework. Weird comparison, I know. But hear me out: Building a chair has some certain steps you have to follow. And these steps always remain pretty much the same, no matter how simple or complex/abstract the chair is. You don’t see people struggling with building chairs because they follow those steps. It’s the same with building CSS layouts. The only difference is that it’s harder to recognize those steps at first glance. But when you do, you just follow them and build the layout. Nothing creative or complex about it. Once you learn the Design Patterns, the layout process becomes straightforward: To celebrate the launch, we're offering "Mastering CSS Layout" at 14% off the regular price until Friday, March 1st. This is your chance to make CSS simple, intuitive, and finally click for you in less than an afternoon of focused, valuable learning. If you are ready to finally understand how CSS layouts work and become confident in your skills or if you want more information, click the link below. It will take you to the course page where you can read more about the course. And if you like what you see, feel free to join. The discount will already be applied when you click the link, you don’t need to add a coupon or discount code. Check “Mastering CSS Layout” here.

Thumbnail Image of Tutorial Announcing "Mastering CSS Layout": The Only Guide You Need To Build Any Layout You Want

I got a job offer, thanks in a big part to your teaching. They sent a test as part of the interview process, and this was a huge help to implement my own Node server.

This has been a really good investment!

Advance your career with newline Pro.

Only $30 per month for unlimited access to over 60+ books, guides and courses!

Learn More

Embedding Figma Files in Storybook

The best design and development teams imbue design and brand consistency across multiple products with design systems . When designers and developers collaborate on and regularly contribute to a design system, communication between designers and developers improves since a design system serves as a single source of truth for design guidelines, workflows and elements. By having a design system, everyone understands what set of colors, typography, components, etc. defines the brand and unifies the digital experience. A tool for building robust design systems is Figma . Unlike most other tools, Figma allows teams to work together on design systems in real-time. Design systems constantly evolve to meet users' growing expectations and/or adopt the latest UI/UX trends and patterns, so using a tool like Figma helps to organize, maintain and easily locate design elements. Plus, Figma provides an Inspect panel , which gives developers an easy way to extract CSS code from any design element. This close mapping to code makes developer handoff more seamless. Designers can edit styles and assets within the design system, and developers can view those changes immediately and quickly adapt them into the products. Pairing Figma with Storybook speeds up this process. With a single Storybook addon, storybook-addon-designs , a Figma design system (or any design system) gets directly embedded in the addon panel of the Storybook UI. Any updates made to the design system are synced to the Storybook addon, so developers don't have to switch back and forth between Figma and Storybook to implement these updates in code. They no longer need to ask for links to the updated parts of the design system. Below, I'm going to show you how to embed a Figma file in Storybook with the storybook-addon-designs addon. For this tutorial, we will recreate a button component from the Material 3 Design Kit with React and write stories that represent the different UI states this component supports (e.g., disabled). Material 3 Design Kit is a Figma community file for Google's open-source Material design system . Before proceeding further, duplicate this file to your Figma account's Draft folder and open it to ensure you have access to the design system. When you navigate to the "Components" page, you should see the buttons in the Figma canvas. To get started, create a new directory named figma-storybook and initialize it with a package.json file: Install React and React DOM as dependencies: Install Storybook via the Storybook CLI: Note : Storybook automatically has built-in TypeScript support, so any components written in TypeScript should work with Storybook with no additional configuration needed. To style the React component, install two packages of the Emotion library as dependencies: Within the root of this project's directory, create a src directory and move the stories directory to this directory. Then, delete the contents of the stories directory. Since we moved the stories directory, let's inform Storybook of the new location of this directory: ( .storybook/main.js ) Looking at the design system in Figma, the button's CSS styles can be copied from the Inspect panel. Using these CSS styles, let's implement the button as a React component. Within the src directory, create a components directory and add two files: Here, we will define the button types filled , outlined , text , elevated and tonal as button categories to avoid any confusion with HTML <button /> types ( button , submit and reset ). Each category comes with five unique visual states: enabled , hovered , focused , pressed and disabled . We can implement the hovered , focused and pressed states purely with CSS via the pseudo-classes :hover , :focus and :active respectively. enabled serves as the default state, and disabled can be controlled via the <button /> element's disabled attribute. Now, let's write the <Button /> component and its styles: ( src/components/Button.tsx ) ( src/components/Button.styles.tsx ) Note : The ::after pseudo-element emulates the ripple effect that's recognizable from Material Design UIs. When the user clicks or touches the button, the ripple spreads out in a circular motion from the point of interaction, like a ripple in water. The ripple gives visual feedback to the user that the element has been clicked or touched. For Storybook to load the button's font family "Roboto," let's wrap stories with a decorator that adds an Emotion <Global /> component for injecting global styles like CSS resets and font faces. In this case, the <Global /> component will import the "Roboto" font family from Google Fonts and make it available to all components rendered in stories. ( .storybook/preview.js ) Within the src/stories directory, let's create a Button.stories.tsx file: We will write two stories for the <Button /> component, one for the enabled default state and another for the disabled state. The story for the enabled state should render a button that's clickable and touchable. The story for the disabled state should render a button that's grayed out and not interactive. ( src/stories/Button.stories.tsx ) Run Storybook and check that the <Button /> component looks and behaves correctly. If a designer decides to change the color of the button in the design system, then you would have to launch Figma and open the design system in Figma before being able to see what the new color is and copy the new color from the Inspect panel. Let's improve this workflow by having the design system readily accessible in Storybook. To connect stories directly to Figma, install the storybook-addon-designs addon as a dev. dependency: Within the .storybook/main.js file, register the storybook-addon-designs addon. ( .storybook/main.js ) In Figma, right-click on the filled button with the text "Enabled" and copy its link. A link makes navigating large Figma files easier by referencing a specific element within the file. When visiting the link, Figma brings the referenced element to the forefront of the canvas and highlights it. Within the src/stories/Button.stories.tsx file, set a design parameter for the Enabled story via the parameters key, like so: Parameters define a story's metadata and determine which addons to apply to a story. In this case, the design parameter tells Storybook to apply the storybook-addon-designs addon to the Enabled story. The object set to design configures the storybook-addon-designs addon for the Enabled story. ( src/stories/Button.stories.tsx ) type specifies the type of resource (e.g., image for image, iframe for iframe, figma for Figma file, etc.) to embed in the addon panel. url specifies the URL of the resource. For the Enabled story, we specify the type as figma and the url as the link to the filled button with the text "Enabled" in the Figma file to embed a live view of the Figma file (zoomed into this button) in the addon panel. Save the changes and wait for the Storybook UI to reload. The view has a "Figma" label in the top-left corner, and the user can move around and zoom in (and out of) the Figma file. Since you have a different link for each component variant, let's repeat these same steps for the Disabled story. ( src/stories/Button.stories.tsx ) Currently, all you can do within the live view is move around and zoom in (and out of) the Figma file. To be able to inspect design tokens and extract CSS code from the live view, we must embed the Figma file with an enhanced spec viewed called Figspec . The storybook-addon-designs addon supports a figspec type, but it requires providing a Figma access token to Storybook so that the addon can tell the Figma API to render the Figma file using Figspec components. Let's generate a Figma access token by: Copy the Figma access token. Then, create a .env file within the root of the project directory and add an environment variable named STORYBOOK_FIGMA_ACCESS_TOKEN that's set to the copied token. ( .env ) Within the src/stories/Button.stories.tsx file, replace all instances of the figma type with the figspec type, like so: ( src/stories/Button.stories.tsx ) Restart Storybook so that the environment variable is loaded. When you click on the button in the live view, a panel with the button's CSS code appears. Note : You can click either the button's background or the button's text to get either's CSS code. If you change the background color of the button in the Figma file, then that change will automatically be seen in the live view. If you find yourself stuck at any point while working through this tutorial, then feel free to visit the main branch of this GitHub repository here for the code. Try integrating your Figma design systems into your project's Storybook UI. If you want to learn more advanced techniques with Storybook, then check out the Storybook for React Apps course by Yann Braga, a senior software engineer at Chromatic and a maintainer of Storybook:

Thumbnail Image of Tutorial Embedding Figma Files in Storybook

Annotating React Styled Components with TypeScript

Styled components redefine how we apply CSS styles to React components. Unlike the traditional approach of manually assigning CSS classes (from an imported CSS file) to elements within a component, CSS-in-JS libraries like styled-components provide primitives for locally scoping CSS styles to a component with unique, auto-generated CSS classes. Consider a simple <Card /> component composed of several styled React components. Each of styled 's helper methods corresponds to a specific DOM node: Here, the <Card /> component's styles, structure and logic can all be found within a single file. styled-components comes up with a unique class name for each set of CSS rules, feeds the CSS to a CSS preprocessor (Stylis), places the compiled CSS within a <style /> tag, injects the <style /> tag into the page and adds the CSS classes to the elements. By tightly coupling components to their styles, we can easily maintain CSS in large React applications. If we need to edit anything about a component, whether it be its color or how it responds to user input, then we can visit one file, which keeps everything related to the component colocated, to make the necessary changes. Unique class names prevent naming collisions with existing class names. Popular CSS-in-JS libraries, such as styled-components and Emotion , come with TypeScript definitions. When pairing styled components with TypeScript, our React application gains all the benefits of a statically typed language while also ensuring component styles remain well-organized. As we write our styled components, our IDE can warn us of any incorrect arguments passed to any of the helper methods, detect typos, perform autocompletion, highlight missing props, etc. Below, I'm going to show you how to annotate React styled components with TypeScript. To get started, scaffold a new React application with the Create React App and TypeScript boilerplate template. Within this new project, install the styled-components library and @types/styled-components , which provides type definitions for styled-components . Within the src directory, create a new directory, components , which contains the React application's components. Within this new directory, create a new file Card.tsx , which contains a <Card /> component. Copy and paste the <Card /> component's source code (from above) into this file. For React Native projects, you would need to install an additional set of type definitions: Then, you must add styled-components-react-native to the list of types in tsconfig.json : ( tsconfig.json ) Suppose we wanted to annotate the example <Card /> component previously mentioned. Annotating a React functional component requires: ( src/components/Card.tsx ) If we want to add to or override the <Card /> component's styles within a parent component, then we need the <Card /> component to accept an optional className prop. By default, all properties are required, but those marked with a question mark are considered optional. ( src/components/Card.tsx ) Now the <Card /> component can be modified from a parent component. ( src/App.tsx ) Suppose a styled component's inner DOM element must be accessed by a parent component. To forward a ref to a styled component, we must pass the styled component to the forwardRef function, which forwards the ref to an inner DOM element that the styled component renders. Annotating a styled component that receives a forwarded ref involves two steps: ( src/components/Card.tsx ) The parent <App /> can obtain a ref to the underlying <div /> element and access it whenever it needs to register event listeners on the component, read/edit DOM properties, etc. ( src/App.tsx ) styled-components lets you easily customize your React application's theme via the <ThemeProvider /> wrapper component, which uses the context API to allow all children components underneath it to have access to the current theme. ( index.tsx ) When adapting styles based on props, TypeScript automatically recognizes the theme property on the props object. Below is a screenshot of passing a function to a styled component's template literal to adapt its styles based on its props. Notice that TypeScript raises no warnings or errors when you reference the props object's theme property. In fact, if you happen to use VSCode and hover over props , then a tooltip with its type definition appears. If you hover over props.theme , then you will see its type definition ThemeProps<any>.theme: any . The any indicates that TypeScript will not raise any warnings no matter what property you try to access from props.theme , even if it does not exist! If I reference a property on the props.theme object that might reasonably be available on it like primary , or something ridiculous like helloWorld , then TypeScript will not raise any warnings for either. Hover over any one of these properties, and a tooltip with the type any appears. By default, all properties on the props.theme object are annotated with the type any . To enforce types on the props.theme object, you must augment styled-components 's DefaultTheme interface, which is used as the interface of props.theme . For now, start by defining the primary property's type as a string (i.e., we might set the primary color of the default theme to red ) in DefaultTheme . ( styled.d.ts ) Note : By default, DefaultTheme is empty . That's why all the properties on the props.theme object are annotated with the type any . Within tsconfig.json , add the newly created styled.d.ts declaration file to the list of included files/directories required by TypeScript to compile the project: ( tsconfig.json ) Now, if you revisit the Card styled component, then you will see TypeScript raising a warning about props.theme.helloWorld since we did not define its type within the DefaultTheme interface. If you hover over props.theme.primary , then a tooltip with its type definition, DefaultTheme.primary: string , appears. Plus, if you revisit the index.tsx file, then you will also find TypeScript warning about the theme object being passed to the <ThemeProvider /> wrapper component: This issue can be resolved by replacing the main property with the primary field: Better yet, you can import DefaultTheme from styled-components and annotate the object with this interface. Back inside Card.tsx , you can refactor the Card styled component by setting background-color directly to the current theme's primary color. To see the final result, visit this CodeSandbox demo: https://codesandbox.io/embed/keen-satoshi-fxcir?fontsize=14&hidenavigation=1&theme=dark Try annotating styled components in your own React applications with TypeScript.

Thumbnail Image of Tutorial Annotating React Styled Components with TypeScript

Styling React Components with styled-components

HTML , CSS and JavaScript form the foundation of all client-side applications. Each of these languages handles a different responsibility. HTML markup semantically organizes content, CSS rules styles content and JavaScript code adds dynamic interactivity to the content. Traditionally, developers build basic client-side applications along this standard separation of concerns, which groups code solely by language (and implicitly, by file type): HTML for structure, CSS for presentation and JavaScript for behavior. However, siloing code this way comes with a caveat. For example, if you have a carousel on your homepage, and you decide to modify its appearance, then you may need to consult three separate files ( .html , .css and .js files) to make the appropriate changes. With modern JavaScript libraries/frameworks, such as React , the separation of concerns shifts from languages to components. Now, all code belonging to a single component lives within a single file ( .jsx / .tsx for React). The component itself, written as a functional or class component, contains methods (lifecycle, render, etc.) that encapsulate its behavior. The JSX syntax within the render method (or within the return statement if written as a function) describes the component's structure. As for the component's presentation, there are two common approaches: Large CSS stylesheets are difficult to maintain, especially when tracking which rules override others and which rules can/cannot be removed. If you write styles using a CSS-in-JS library, then all styles belonging to a component exists alongside the component within a .jsx / .tsx file (or .js file if imported from a separate file). When the component is no longer used within the application, then deleting the component's styles is as simple as deleting the component itself. For a React component library, CSS-in-JS libraries provide lots of functionality to supercharge components' styles: Below, I'm going to show you how to add styled-components to a React component library and how to style a component with styled-components . To understand how styled-components works, let's walkthrough a simple example: ( src/components/Heading.jsx ) ( src/App.jsx ) Note : By convention, the names of styled components are prefixed with Styled , which tells developers distinguish styled components from other components. Here, the <Heading /> component renders the styled component <StyledHeading /> , which is an <h1 /> element that is bolded, colored black and has a font size of 4rem . In fact, you can customize the styles based on props passed to the styled component: ( src/components/Heading.jsx ) ( src/App.jsx ) The most common way to write styled components is with tagged template literals . Appending a template literal to the end of a tag function name executes the tag function with the template literal and its placeholder expressions passed as arguments. Example : When the logTagFnArgs function is called, the template literal is broken up into smaller substrings based on the positions of the placeholder expressions. As you can see, the substrings that come before and after the placeholder expressions (including empty strings if the placeholder expression is located at the start/end of the template literal), such as "Sum of " before ${x} , are stored within an array that's passed as the first argument to logTagFnArgs . Each placeholder expression is passed as a separate argument to logTagFnArgs . With the rest parameter syntax, we can have the function accept these separate arguments as a single array, hence why the exps array contains the values 5 ( x ), 10 ( y ) and 15 ( x + y ). In the styled-components example, styled.h1 is a tag function. Knowing that styled.h1 returns a React component, we can write our own basic implementation of the styled.h1 tag function. First, establish a list of HTML tags you want the styled object to support. Let's start off with <h1 /> , <h2 /> , <h3 /> , <h4 /> , <h5 /> and <h6 /> tags. Then, place them within a styled object, which will be exported for other files to import. createStyledComponent will be a function that accepts a tag as an argument (since it must know which HTML element to render), and it will style and return a React component based on the tagged template literal. Due to the closure, the anonymous function returned by createStyledComponent allows the functional component to access the tagged template strings and expressions. Also, some of the expressions are functions that involve props passed to the functional component. Using the tagged template strings, expressions and props, the functional component takes these values and applies styles to the element accordingly. parseStyles parses the tagged template literal into an object that contains the CSS rules as key/value pairs. All function expressions are evaluated with the component's props passed as its argument. For example, if the component has no props passed to it, then this... becomes... And the element's style attribute is set to this object. All excess whitespace around the rules and their properties/values are removed. All non-integer and non-string values (booleans, functions, arrays, etc.) are omitted. Altogether... ( src/styled.js ) If we substitute styled-components with this implementation, then the application still works. ( src/components/Heading.jsx ) Nevertheless, this implementation only inlines styles directly on the element. It does not generate custom CSS class names and cannot process SCSS-like syntax with nesting, such as &:hover . styled-components uses the CSS preprocessor Stylis to compile code written with this syntax into CSS code. The purpose of this implementation is to demonstrate how styled-components works under-the-hood at a high level. Let's clone the repository react-d3-charts , a component library that contains customizable D3 visualizations written in React and TypeScript. Currently, this repository only has one visualization component, a scatterplot. Inside of the project directory, install the dependencies: Install the library  styled-components as a dependency. Next, install @types/styled-components , which has TypeScript types for the styled-components library, as a dev. dependency. Inside of the src/components/XAxis.tsx file, which houses the component that renders a x-axis for the scatterplot component, observe that the two <text /> elements draw upon the same set of attributes and values: font family, font size and fill. If the component had many <text /> elements that rely on these same attributes, then there will be more repetitive JSX code. Let's place these styles within a single styled component named StyledText . Swap out the <text /> element with the <StyledText /> component and omit the fill , fontFamily and fontSize attributes. If you inspect this styled component via the developer console, then you will see a custom CSS class name added to the <text /> element. We can create styled components for the <path /> and <line /> elements. If you inspect these styled components via the developer console, then you will see custom CSS class names added to the <path /> and <line /> elements. If you check the contents of src/components/YAxis.tsx , then you will see that the y-axis has the same elements with the same styles as the x-axis: <path /> , <text /> and <line /> . We can refactor the code to make the styled components <StyledPath /> , <StyledText /> and <StyledLine /> reusable for the <YAxis /> component. Create a new folder src/styled and a new file src/styled/index.ts . Move all of the styled components into src/styled/index.ts and export them. ( src/styled/index.ts ) Inside of both src/components/XAxis.tsx and src/components/YAxis.tsx , substitute the <path /> , <text /> and <line /> elements with the styled components <StyledPath /> , <StyledText /> and <StyledLine /> exported from the src/styled/index.ts file. ( src/components/XAxis.tsx ) ( src/components/YAxis.tsx ) For a final version of this tutorial, check out the GitHub repository here . Add more styled components to this library! If you already maintain a React component library, then try adding styled components to your library.

Thumbnail Image of Tutorial Styling React Components with styled-components

Encapsulated CSS

Photo by  Mika Baumeister  on  Unsplash Most modern frameworks, like React, use components as their foundation. They do this for a few reasons, but a crucial one is that components allow you to break your app into simple single-purpose parts that can then be composed together to solve more complex needs. Unfortunately, CSS was invented to solve problems from the top down,  starting with more general rules to more specific rules . Components encourage you to start from the bottom up, breaking your pages down into the more specific parts first, often in isolation to the whole, and then composing them together.  Many tools and naming conventions have been created to help us maintain our style sheets like BEM, SASS, Less, CSS-Modules, and CSS-in-JS, but they all fall short in the one problem that tooling can never solve:  Which component should be in charge of which styles? The answer to this question is key to making composition work, especially where web layout is concerned. That answer is Encapsulated CSS. Encapsulated CSS is a term that summarizes the rules of how to apply CSS styles in a composable way. It’s based on the programming principle of encapsulation. If we were to define encapsulation in a language-agnostic way, encapsulation involves grouping related things and restricting access to those things except through appropriate channels. For example, many program languages utilize a module system, which follows the principles of encapsulation. When you import a module like React , you get a group of functions that help you build a React application, but you don’t have access to the actual internals that make a React applications work.  Encapsulated CSS is based on that same principle. It’s a methodology that helps group-related styles at the correct component level and only applies styles through appropriate channels. There are two essential principles of Encapsulated CSS: The first principle is:  “Elements do not lay themselves out.”  When I say that elements don’t lay themselves out, I am specifically speaking to an element's position, size, and margin. The second principle is:  “Elements style themselves and layout only their immediate children.”  Properties that involve the border-box and inward are considered part of the component and therefore they should be applied at the element level. This also includes the layout environment of the component’s immediate children. Therefore, it is the parent component’s responsibility to set its direct children's position, size, and margin. If a component shouldn’t set its own layout properties, how do you set them? I mentioned earlier that encapsulation allows you to access properties through appropriate channels. These appropriate channels in components are props and the direct child combinator. In React, we use props as inputs to our component, much like functions use arguments. Our components use these props in our components. Just like we can expose a label or an onClick prop, we can expose layout properties like margin-top or min-width: Using props in this manner works well with one or two properties, but it becomes unwieldy quickly as you expose more and more properties. The props of your component should also be a reflection of what your component does. Having an arbitrary marginLeft prop doesn’t make sense on a calendar component. The other channel for adding styles is using the direct child combinator in the parent component. This tool allows us to select any or all of our parent containers’ immediate children and apply the layout styling we need.  Let’s take the following Blog Post component: Applying styles that follow the principles of Encapsulated CSS, we could do something like this: In the above stylesheet, the .blog-post and .blog-title classes set their own non-layout-related styles. However, when we needed to set layout properties on any of the elements, we used the direct child combinator to select the appropriate children of the .blog-post to set those properties. For example, we use  .blog-post > h2 to select the h2 tags that were direct children of the .blog-post class to set the layout properties we needed. At this point, one might start to ask why bother to go through this ceremony of adding a separate rule for the direct children just to add a layout property? One could argue that you could write less CSS by just applying the layout properties to the corresponding element.  First of all, because we didn’t add any layout properties to the .blog-post class, this blog post component can safely be placed in any context and not interfere with the layout environment that it is being put. The children can also now be refactored into components, if needed, and won’t bring along the baggage of the layout environment it was initially created in. It also helps with debugging. One of the most significant difficulties of debugging CSS is determining where your styles are coming from. It is easier to track down styles if you have rules in place where those style properties originate. If the style you are looking for is layout-related, you know that the style must be on the parent element. Encapsulated CSS is about creating restrictions that make sense and encourages you to write code that is easier to maintain and refactor. By following these rules, your components will become much easier to refactor and compose anywhere in your app.

Thumbnail Image of Tutorial Encapsulated CSS

Dynamic Visualisation with Angular

When faced with a need to visualise data, many developers' first instinct is to reach for a 3rd-party charting library. There's nothing wrong with this: there are several robust and full-featured libraries out there, and it's usually smart to leverage existing, good quality code. But we shouldn't forget that Angular, coupled with modern CSS features, also provides a great base on which to create our own, bespoke visualisation components. Doing so gives us the ability to tailor them to our exact use-cases, and avoid the inevitable trade-offs and bloat that comes with trying to solve for the general case of visualisation and charting. Also, creating visualisation components is just plain fun. In this article, we'll explore the process of creating a bar chart component for Angular. Even if you've created similar components before, the approach here might surprise you. We won't be rendering to a canvas element, or to dynamic SVG. We won't be using D3, or any dependencies besides those that come with a standard Angular CLI app. We won't be using any listeners or polling to detect resizes and run complex and flaky layout code. Instead, we'll strive to use modern CSS features, in particular grid and custom properties, to build the component's layout in a declarative and automatically responsive way. The finished chart can be viewed in this simple demo , or in a more complex demo . The complete code for the chart and both examples can be found on GitHub The first thing to do is create our component. We can use Angular CLI's schematics to generate one for us: In a theoretical sense, we can consider our component as a function that maps from its inputs to a rendered output (i.e., the chart). So, let's start by identifying what the input data should look like by defining some TypeScript interfaces inside bar-chart.component.ts : Our chart's raw data will be stored in this structure, and supplied to our component using @Input() properties that we'll define in the BarChartComponent class in bar-chart.component.ts : We'll need to define some additional inputs later, for things like the chart title, but these will suffice for now. Next we'll the basic layout structure of our component. We start with a simple mockup of our bar chart component, placed within the context of a skeleton app page: When building components, it is important to think of layout in terms of "inner" — those aspects controlled by the component code itself — and "outer" — those controlled by the surrounding content. In its most basic form, our component is just a box placed within another larger box (the page): Everything that goes on inside the inner, purple box is the responsibility of the component, but it should make few or no assumptions about the size and position of the box within the larger layout. Instead, it should adapt to the size of its container. This will make it more generic, and more easily re-usable in different situations and contexts. By leaving the positioning and sizing of our component up to its consumer, the dimensions of our component's layout box become an input, as important (and unknown) as the data we'll be showing as columns, series and categories. We could read these dimensions explicitly from the DOM and calculate our entire layout in JavaScript, but this is difficult to do in a truly performant and bulletproof way (although CSS Houdini 's Layout API may change this, when it arrives). To achieve a responsive inner layout without having to calculate everything ourselves, we will use CSS Grid layout. The design our grid, we begin by breaking up the mocked-up content into sections: We can see that, in essence, our component consists of five areas: The next step is to break the layout up further, into the rows and columns of our layout grid, which we then define in bar-chart.component.scss . Since we want our component to be responsive. We also need to consider how these will be sized relative to the total available space. CSS grid provides a great deal of scope of how a row or columns can be sized. But at a high–level, there are four strategies: It is this ability to control the sizing strategy of different sections of our component that makes using grid such a compelling alternative over rendering to canvas or SVG. Even though SVG is responsive in the sense of being scalable to any size without losing detail, its positioning system is extremely primitive, making it impossible to create truly responsive visualisations in a declarative way. Now let's break our design down further, into rows and columns: Note that we will be using grid's named-lines capability to identify important offsets in our grid. This is important to make the CSS we write for each section structurally independent of the rest of the grid. In contrast, hardcoding exact row and column offsets makes it much harder to modify the grid structure later, if we want to introduce a new element, such as a row of controls. We have a fixed set of five rows, and they can be defined as follows: Note that only one of our rows, the data row, will be fully flexible. The others will size to fit their content instead. We are also using the minmax(...) function to give the flexible row a minimum and maximum size. In this, case we give a small minimum of 10em , to ensure that the data at least remains visible, while letting the data row grow as large as it can with a 1fr maximum. Defining the columns of our grid is more complicated, as there will be a dynamic number of them. Fortunately CSS grid provides for this situation. Here we're using a repeat(...) function expression to specify the dynamic data columns. Let's look at it isolation: The repeat(...) expression indicates that we would like to repeat the following column definition some number of times. This can be a static number, but in our case the repeat count is a CSS custom property/variable, called --column-count . This variable is the bridge between our component and its stylesheet, and we'll see later how it can be supplied by the JavaScript code. The [col-start] gives each repeated column a name. These names don't have to be unique, as we can specify one by supplying an index with the name, e.g., col-start 1 , col-start 2 , etc. This lets us place content in a particular column without worrying about the rest of the grid's details. Finally, minmax(5em, 1fr) makes each column size between a minimum of 5em and an unbounded maximum, similarly to how we constrained the data row. Because there may be more than one column, any available space will be shared equally between them. With the grid structure of our component defined, we can begin adding the content. We'll progress through each piece of content: We'll start simple, with the chart title. We can add a new input to configure this: And, if it's set, we'll bind it to an element in the component template: And finally we can add some styles for this element: The legend displays a key of the chart series. We already have an input for this, so we now need to render it into our template: Here we see our first use of a CSS custom property, --color , which we're binding to the value of the color field of the series. This lets us pass a value from the JS realm into CSS, where we can use it in place of a static value: Here we've used it as the background color of a pseudo element. This wouldn't be possible with a regular style attribute binding, and we'd have to introduce an additional element into our HTML. This approach keeps our markup simple. Custom properties help us develop a clean abstraction between the component's JS, template, and stylesheet. The template is only responsible for binding a single, domain-specific value, which the stylesheet bind to whichever elements and properties it wants, without the knowledge of the JS or template. Now we come to the heart of our grid, the categories. The final piece of our CSS grid configuration is to supply the --category-count CSS property we used earlier in the grid-template-columns definition. As this is declared on the host element, we can't bind it in the template. Instead, we can use a host-binding in the component class: We also want to calculate and bind another property: ---maxValue . This will let us communicate to CSS Recall that our category data structure looks like this: For each category, we need to render both values array, as coloured bars in the data area, and its label property, in the axis area. We'll begin with a single loop over the categories field: For the category values , we'll render .category div with a nested ngFor to output a .bar for each value: We move the .category div into the correct position by binding its grid-column style to a string of the form col-start {i+1} . This ensures it will be placed into the correct repeated column. For each .bar we won't bind any styles directly. Instead, we'll supply two CSS variables: --value , which contains the raw frequency value from the values array, and --color , which contains the series color from the series field. We'll use both in the component stylesheet: The .category div is a flex container that aligns its items to the end, which is equivalent to aligning their bottom end to the x axis line. Here we're using the --color property as the background color. However, by abstracting it using a property, we could have media queries to change how it is used, such as applying it as an outline when printing, without requiring a change to the template. The --value property is being used in a calc(...) function to determine the height of the bar. By dividing it by a second, --max-value property, then multiplying it by 100%, we can scale the height of the .bar in a declarative way. In order to supply --max-value , we can use setter function on categories to calculate and bind it: When dealing with unknown data, text labels are a real source of pain. Long labels can easily overflow the container. On a bar chart, the best approach for x axis labels is usually to rotate them at a 45-degree angle. This prevents them overflowing into each other, while being more readable and space efficient than 90-degree labels. To rotate the labels, we can use CSS transforms: However, CSS transforms are not taken into account for layout purposes. The y axis area will be sized as if all the labels were unrotated, giving it a single-line height, and meaning these labels will overflow the bottom of the container. To prevent this, we can use padding-bottom and a bit of trigonometry. Because percentage padding is always calculated based on an element's width, we can use it on the .label-text wrapper to make each label's height proportional to its width. And trigonometry tells use that a horizontal line rotated to 45-degrees covers approximately 70% of its length in the vertical direction. Therefore, a padding-bottom: 70% value on each .label-text will ensure the y axis area is always large enough to contain the rotated labels. Since we don't know the range of the data, we face the problem of producing a range and ticks for the y axis. Our options are: In our implementation, we'll attempt the third choice using an algorithm invented by Paul S. Heckbert for generating "nice" axis labels. The approach was first detailed by Heckbert in the book Graphics Gems, and it works based on the observation that power-of-ten multiples of 1, 2 or 5 tend to look best. Check the example project for the complete implementation. But, the end result is a function niceTicks(min, max, tickCount): number[] that we can use in our categories setter: We render the y axis ticks in the template using another *ngFor loop: To correctly layout the ticks along the length of the y-axis container, we'll use a vertical flexbox with space-between justification and a reverse order: However, the intrinsic height of the .y-tick boxes will prevent them being at exactly the right location. We can solve this by setting the .y-tick height to zero, and applying a CSS transform to move the nested .y-tick-value box into place: By avoiding the use of absolute positioning on the ticks, we ensure that the width of the .y-axis container is still calculated based on the width of the labels, and will be sized correctly without any need to perform JS-based measurement of the element sizes. All that remains is to complete the styling of the axis and the ticks using CSS borders and pseudo elements for the tick marks themselves. We now have the essentials of laying out of chart done. However, we're not yet done. There's still a bit of work to tidy up the styling–applying margins, padding and colours to various elements until we have an attractive looking chart. The nature of this work depends upon the particular look you're trying to achieve, but you can examine the example project for a possible example. It is useful to define sizes, such as margins and padding, using em values, so they scale in proportion to the font size. This gives the component consumer an easy way to scale the chart's text and internal sizes using just the font-size CSS property. At this point we have a working bar chart component that responds flexibly both to different data sources, and the size constraints applied to it by its surrounding layout container. If we were to continue to develop it, there's many more features we could add, such as templated columns, better handling of over-sized tick and category labels, or display-mode controls for stacked and scaled bars. The possibilities are endless, although we should always be careful to evaluate the additional complexity each feature introduces into our codebase against the value it provides. Jon Rimmer is a software developer who lives and works in London.

Thumbnail Image of Tutorial Dynamic Visualisation with Angular