close icon
daily.dev platform

Discover more from daily.dev

Personalized news feed, dev communities and search, much better than what’s out there. Maybe ;)

Start reading - Free forever
Start reading - Free forever
Continue reading >

Styled Components Form Example: A Guide

Styled Components Form Example: A Guide
Author
Nimrod Kramer
Related tags on daily.dev
toc
Table of contents
arrow-down

🎯

Learn how to create visually appealing and functional forms in React using Styled Components. Explore the advantages, design considerations, validation logic, and advanced techniques for building robust forms.

Creating visually appealing and functional forms in React can be challenging. Most developers would agree that balancing code structure, validation logic, and intuitive design takes effort.

Luckily, Styled Components makes crafting React forms more manageable. This post will demonstrate an accessible Styled Components form template that handles:

  • Responsive layout and styling
  • Built-in validation with Yup
  • Reusable UI components
  • Integration with frameworks like Next.js and Gatsby

In short, you'll have a production-ready form to quickly build forms that convert.

We'll start by exploring the advantages of Styled Components for forms, then walk through a complete code example. You'll learn:

  • Initial setup with Styled Components
  • Design considerations for accessibility
  • Implementing validation logic
  • Advanced techniques like props, attrs, and variables
  • Using Styled Components across popular React frameworks

By the end, you'll have a reusable Styled Components form foundation to streamline development.

Introduction to Styled Components in React Forms

Styled components is a popular CSS-in-JS library that allows you to write component-scoped CSS using JavaScript template literals. It can help create readable, maintainable forms in React apps.

The goal of this guide is to demonstrate simple form building with styled components following best practices like:

  • Structuring for modularity and reusability
  • Input validation
  • Accessible and mobile-friendly UX

We'll build a basic contact form in React using features like:

  • Template literal styles
  • Custom CSS properties
  • Polymorphic as prop
  • Passing props
  • Attribute selectors

By the end, you'll have a solid foundation for leveraging styled components to create functional, resilient React forms.

Understanding CSS-in-JS with Styled Components

Styled components lets you write actual CSS code using JavaScript template literals. This allows component-scoped styling, away from traditional global CSS files. Some key advantages:

  • No name collisions - unique class names get auto-generated
  • Code splitting - no unused styles in the final bundle
  • Easier deletion - no side effects when removing a component
  • Painless maintenance - styles live next to components using them

It's a popular CSS-in-JS tool as it doesn't require learning a special syntax. You simply write normal CSS.

Advantages of Styled Components for React Forms

Compared to global CSS, styled components offers useful benefits when building React forms:

  • Scoped styles - no accidental breakage across components
  • Reusable - extract and share common styles
  • Modular - import only what each component needs
  • Dynamic - adapt based on props, themes, device sizes etc.

This improves long term maintainability of forms vs using global CSS files.

Setting the Scene for a Styled Components Form Example

In this guide, we'll build out a simple contact form with fields for name, email and message. Goal is to cover core techniques like:

  • Passing props for dynamic styles
  • Modular structure for reusability
  • Client-side validation for UX
  • Mobile-friendly responsive form

By the end, you'll know how to leverage styled components for creating readable, robust React forms.

Initial Setup for a Styled Components Form in React

Creating the App.js Structure with Styled Components

To start, we need an App.js file that will contain our main React application logic and routing. This is where we'll wrap our <Form> component that uses styled-components.

Here's an example App.js structure:

import React from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";

import Form from "./Form"; 

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Form />} />
      </Routes>
    </Router>
  );
}

export default App;

This wraps the <Form> component in React router so we can access it on the homepage route.

Importing Styled Components and Form Dependencies

In our Form.js file, we need to import styled-components along with any other libraries we'll use for handling form logic and validation:

import React from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";

import styled from "styled-components";

This imports React, react-hook-form, Yup for schema validation, and styled-components so we can start building our form styles.

Drafting the Basic Form Structure in Form.js

With our imports set up, here is an example basic structure for Form.js:

const Form = () => {

  return (
    <StyledForm>
      // Form fields and logic here 
    </StyledForm>
  );
};

const StyledForm = styled.form`
  // Styles here
`;

export default Form;

This creates a Form component that wraps form elements in a <StyledForm> wrapper to apply styled-components styles.

We can now start adding form fields, validation, and styling using styled-components in a React form.

Designing Form Styles with Styled Components

Setting a Container with Max-Width Using Styled Components

To center align the form and set an appropriate max-width for readability on all viewports, we can create a Container component with styled-components:

const Container = styled.div`
  max-width: 600px;  
  margin: 0 auto;
  padding: 2rem;
`;

The max-width keeps the form content constrained, while margin auto centers it. The padding adds breathing room around the form.

Applying Normalize CSS to Form Elements

It's important to apply normalize CSS reset styles so form elements render consistently across browsers:

const Input = styled.input`
  box-sizing: border-box;
  margin: 0;
  padding: 0.5rem;  
`;

This ensures padding, margins and box model behavior is consistent.

Styling Input Fields with Consistency and Accessibility

We can build on the base input component to add visual styles:

const Input = styled.input`
  border: 1px solid #ccc;
  border-radius: 4px;
  
  &:focus {
    outline: 2px solid blue;
  }  
`;

The borders, border-radius and focus outline improve usability.

Creating Interactive Buttons with Styled Components

Buttons should have a pointer cursor and hover effect:

const Button = styled.button`
  cursor: pointer;
  
  &:hover {
    background: blue;
    color: white;
  }
`;

This signals interactivity to the user.

Displaying Error Messages with Clear Visibility

We can style error messages to stand out:

const ErrorText = styled.div`
  color: red;
  margin-top: 0.5rem; 
`;

The red color draws attention, while the margin spacing ensures other elements don't visually collide with the text.

sbb-itb-bfaad5b

Implementing Form Logic and Validation in React

Defining Input Validation Schema with Yup

To validate inputs in a React form built with styled components, we can create a validation schema using Yup. This allows us to define things like:

  • Required fields
  • Email format
  • Password complexity rules
  • And more

Here is an example schema for a login form:

import * as yup from 'yup';

const schema = yup.object().shape({
  email: yup.string().email('Invalid email').required('Email is required'),
  password: yup.string()
    .min(8, 'Password must be at least 8 characters') 
    .required('Password is required'),
});

We can then pass this schema into React Hook Form's useForm() hook as we'll see next.

Initializing useForm Hook with Styled Components

To handle form state and validation, we'll use React Hook Form's useForm() hook. Here is an example initialization:

import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';

import { schema } from './schema';

const defaultValues = {
  email: '',
  password: '',
};

const { register, handleSubmit } = useForm({ 
  defaultValues,
  resolver: yupResolver(schema),
});

We pass the schema to a Yup resolver so validations are run against it. The register() function is used in the inputs.

Handling Form Submission with Styled Components

When the form is submitted, we can run validations and handle the results:

const onSubmit = async (data) => {
  try {
    // Call API or handle form data

    reset(); // Clear form
  } catch (error) {
    console.log(error);
  }
}

const { handleSubmit } = useForm();

<Form onSubmit={handleSubmit(onSubmit)}>
  {/* Form inputs */}

  <Button type="submit">Login</Button> 
</Form>

If validation fails, the errors will be surfaced automatically. If it succeeds, we can process the data and clear the form.

Conditionally Displaying Error Messages

To display any validation error messages, we can use React Hook Form's formState property:

const {
  register,
  formState: { errors }
} = useForm();

return (
  <Form>
    <Input {...register('email')} />
    
    {errors.email && <Error>{errors.email.message}</Error>}

    <Button type="submit">Submit</Button>
  </Form>
);

Here we check if there are any errors for the email input and display the message if so. This allows handling errors for each input separately.

Advanced Styled Components Techniques for Forms

Dive into more complex aspects of styled-components, such as props, attrs, and selectors, and how they can be utilized in form design.

Leveraging Styled-Components Props in Form Elements

Styled components allow you to pass props to style elements dynamically. For example, you can create a FormInput component and pass a size prop to change the height:

const FormInput = styled.input`
  height: ${props => props.size === 'large' ? '48px' : '36px'};
`

<FormInput size="large" />

This helps reduce code duplication. You can also pass complex objects via props and access the values:

const theme = {
  colors: {
    primary: 'blue'
  }
}

const FormInput = styled.input`
  border: 1px solid ${props => props.theme.colors.primary}; 
`

<FormInput theme={theme} />

Utilizing the Styled-Components attrs Constructor

The attrs constructor allows you to set default attributes on elements:

const FormInput = styled.input.attrs({
  type: 'text',
  required: true  
})`
  // styles
`

<FormInput /> // type="text" required 

This reduces repetitive code when setting common attributes.

Applying CSS Custom Properties with Styled Components

You can create CSS custom properties (variables) that can be reused across styled components:

const vars = css`
  --colorPrimary: hotpink;
`

const FormLabel = styled.label`
  &:after {
    content: "*";
    color: var(--colorPrimary); 
  }
`

<FormLabel />

This allows consistent theming across components.

Creating Polymorphic Props for Reusable Form Elements

The as polymorphic prop allows you to dynamically change the HTML tag rendered by a component while retaining its styling:

const FormElement = styled.input`
  display: block;
  // shared styles  
`

<FormElement as="select" />
<FormElement as="textarea" /> 

This creates reusable base components where only the tag changes.

Handling Vendor Prefixes and Style Normalization

Libraries like polished help handle vendor prefixes:

import { normalize, transitions } from 'polished'

const FormButton = styled.button`
  ${normalize()}
  ${transitions(['background'], '0.3s')}
`

You can also create a global NormalizeStyles component for normalization across browsers.

Integrating Styled Components with Frameworks

Styled components can be seamlessly integrated with popular JavaScript frameworks like Next.js and Gatsby to style forms. Here are some tips for usage with each:

Usage of Styled Components with Next.js Forms

To use styled components with a Next.js form:

  • Install the styled-components and babel-plugin-styled-components packages
  • Configure Babel to use the styled components plugin
  • Import styled components in your pages/components
  • Style form elements using template literals

For example:

import styled from 'styled-components';

const Form = styled.form`
  max-width: 500px;
  background: white;
  padding: 20px;
`; 

export default function ContactForm() {
  return (
    <Form>
      // form elements
    </Form>
  )
}

Benefits of this approach:

  • Automatic vendor prefixing
  • Server-side rendering support
  • Theming capabilities
  • Styling abstraction from components

Leveraging Styled Components in Gatsby Forms

Similar steps can be followed to use styled components with Gatsby:

  • Install styled components and the babel plugin
  • Configure the Gatsby babel config
  • Restart the dev server
  • Import and use styled components

For example:

import styled from 'styled-components';

const FormWrapper = styled.div`
  font-family: 'Arial';
  
  form {
    background: papayawhip;
  }
`;

export default function Contact() {
  return (
    <FormWrapper>
      <form>
        // form fields
      </form>
    </FormWrapper>
  )
}

Benefits for Gatsby:

  • Theming and styling abstraction
  • Works with Gatsby SSR
  • Code splitting automatically handled
  • High performance

So in summary, styled components integrate smoothly with both Next and Gatsby for crafting form UIs, providing useful capabilities on top of those frameworks.

Conclusion: Crafting Forms with Styled Components in React

Summarizing the Styled Components Form Example

Here are some key takeaways from this guide on creating forms with styled components in React:

  • Styled components allow you to write actual CSS code to style your components. This makes it easy to create reusable and modular styles.

  • Using React Hook Form along with Yup for validation keeps the form logic separate from the UI code. This results in better organized and maintainable forms.

  • Focusing on the user experience with things like clear labels, validation messages, and a simple layout leads to better conversion rates.

  • Styled components has features like props and attrs that make dynamic styling simple. You can update CSS values based on component props.

  • Following best practices like normalize CSS, using CSS custom properties, adding vendor prefixes, etc. makes your forms robust and consistent across browsers.

Overall, styled components enables crafting scalable, dynamic forms that provide a great user experience.

Further Learning and Documentation for Styled Components

To learn more about building forms with styled components and React, refer to these additional resources:

The styled components documentation in particular has extensive examples for dynamic styling, global styles, server-side rendering, and more that are useful for building React forms.

Related posts

Why not level up your reading with

Stay up-to-date with the latest developer news every time you open a new tab.

Read more