BestPractices
CSS

Here are general guidelines for slicing components into outer and inner components, ensuring separation of concerns, reusability, and maintainability:

1. Define Responsibilities Clearly

Outer Component: Handles positioning, layout, and external context (e.g., margins, paddings, widths, and container-specific styles). Inner Component: Manages its internal structure and child element arrangements (e.g., flexbox/grid for content alignment, gaps, and spacing between child elements). 2. Follow a Top-Down Approach Start with the outermost structure, progressively breaking it into smaller, isolated components. Example:

<div className="layout-container">
  <div className="positioning">
    <InnerComponent />
  </div>
</div>

2. Avoid Cross-Responsibility Styling

Do not mix positioning (e.g., margins, widths, and external paddings) and internal content alignment (e.g., justify-center, items-start) in the same component. Let the outer component dictate its size and placement within the parent, while the inner component focuses solely on how its own children are displayed.

3. Make Components Reusable

Inner components should be "black boxes" that:

Work in any container without requiring external knowledge. Accept only necessary props (e.g., className for overrides or children for dynamic content).

4. Use Composition Over Nesting

Leverage props or slots to allow the parent to inject dynamic content into inner components instead of over-nesting. Example:

const OuterComponent = ({ children }) => (
  <div className="outer-layout">{children}</div>
);
 
const InnerComponent = () => (
  <div className="inner-layout">
    <p>Static or reusable content</p>
  </div>
);

5. Use Tailwind Utilities to Enhance Modularity

Outer Component Utilities: Focus on container-based classes like mt-, w-, pl-, relative, or z-. Inner Component Utilities: Use structural classes like flex, grid, justify-, gap-, or items-* to organize children.

6. Ensure Flexibility with Tailwind Breakpoints

Outer components handle layout-level responsiveness (e.g., lg:w-2/5, sm:pl-4). Inner components focus on content alignment adjustments (e.g., lg:gap-6).

7. Test Components in Isolation

Verify that the inner component can function independently without its outer container. Ensure that outer components can hold different child components, proving their flexibility.

8. Document Clear Boundaries

For larger teams, define rules like:

"Outer components handle placement and spacing." "Inner components manage alignment and child arrangements."

9. Avoid Unwanted Margins or Paddings in Inner Components

Ensure child components (inner components) do not affect outer components through unwanted margins or paddings. Margins and paddings should be avoided in inner components and replaced with gap utilities for internal spacing.

10. Use gap Utilities for Internal Spacing

Use gap utilities (e.g., gap-x-, gap-y-) for arranging elements inside inner components. This ensures a clean and consistent approach to spacing without relying on margins or paddings.

11. Use cn or clsx for Conditional ClassNames

Leverage utilities like cn or clsx to handle conditional className values in a clean and maintainable way. This improves readability and reduces logic clutter within JSX code.

12. Example in Practice

Full Component:

<div className="mt-10 pt-8 lg:w-2/5 relative">
  <div className="flex flex-col h-full items-start justify-center gap-y-4">
    {/* Child elements */}
  </div>
</div>

Sliced Version: Outer Component:

const OuterComponent = ({ children }) => (
  <div className="mt-10 pt-8 lg:w-2/5 relative">{children}</div>
);

Inner Component:

const InnerComponent = () => (
  <div className="flex flex-col h-full items-start justify-center gap-y-4">
    {/* Child elements */}
  </div>
);

Usage:

<OuterComponent>
  <InnerComponent />
</OuterComponent>

These guidelines keep components clean, modular, and maintainable while promoting reusability in any layout or context.