Tailwind CSS Break Before
Break Before is a CSS property that controls page or column breaks before an element. This is helpful when dealing with multi-column layouts and print styles where controlled breaks are necessary.
Tailwind CSS simplifies the use of break before properties by providing a range of utility classes that you can effortlessly apply to your elements. This guide delves into using these utilities, explaining how to use them in various contexts to achieve precise control over content flow.
Class | Properties | Example |
---|---|---|
break-before-auto | break-before: auto; | <div className="break-before-auto"></div> |
break-before-avoid | break-before: avoid; | <div className="break-before-avoid"></div> |
break-before-all | break-before: all; | <div className="break-before-all"></div> |
break-before-avoid-page | break-before: avoid-page; | <div className="break-before-avoid-page"></div> |
break-before-page | break-before: page; | <div className="break-before-page"></div> |
break-before-left | break-before: left; | <div className="break-before-left"></div> |
break-before-right | break-before: right; | <div className="break-before-right"></div> |
break-before-column | break-before: column; | <div className="break-before-column"></div> |
Overview of Break Before
Adding the Break Before
To insert a break point immediately before an element, such as a paragraph, heading, or a specific container— use the break-before-*
utilities.
In this snippet, the break-before-page
class (which corresponds to standard CSS break-before: page;
) ensures that when this layout is printed, the second container will force itself onto a new page or column.
export default function BreakBeforeSample() { return ( <div className="h-screen w-screen p-8"> {/* Section 1: Includes an image and text */} <div className="bg-white p-6 mb-4"> <img src="https://images.unsplash.com/photo-1487017159836-4e23ece2e4cf" alt="Sample" className="rounded mb-4" /> <h2 className="text-2xl font-bold"> Section One </h2> <p className="mt-2"> This area demonstrates the primary content for the first section. We might want a break after this section if we are preparing a layout that transitions into a new part of the document (e.g., a new page in a print layout). </p> </div> {/* Applying the break-before behavior */} <div className="break-before-page bg-white p-6 mb-4"> <h2 className="text-2xl font-semibold"> Important Layout Transition </h2> <p className="mt-2"> This element is configured to enforce a page break immediately before it, ensuring this and subsequent content appears on a fresh page when printed. </p> </div> <div className="bg-white p-6"> <h2 className="text-2xl font-semibold"> Next Segment </h2> <p className="mt-2"> After the forced break, this section will come below the "Important Layout Transition" section in a new page when printed. </p> </div> </div> ); }
States and Responsiveness
Tailwind's utility classes for break-before
properties can also be combined with state and responsive modifiers to apply specific breaks based on states like hover
and focus
and the screen width.
Hover and Focus States
Break before is often considered for printed or column based layouts. When using columns, you can also use it with state modifiers to apply breaks only when certain states are active. For example, you might want to force a column break before an element only when a user hovers it.
You can achieve this by prepending state modifiers to the utility class. Ensure your element is part of a multi-column layout for break before to have an effect.
In the below example, the browser applies a column break before the second element when the user clicks on it.
export default function HoverInteraction() { return ( <div className="columns-1 h-screen w-screen p-6"> <div className="bg-white transition-all"> <h2 className="text-2xl font-semibold"> First Column </h2> <p> When the below section is clicked, it applies a <code>break-before</code> forcing this block to appear in a new column, highlighting how hover states can dynamically adjust layout flows. </p> </div> {/* Breaks on Focus */} <div tabindex="0" className="focus:break-before-column bg-white pt-6"> <h2 className="text-xl font-medium"> Breaks on Click </h2> <p> When you click this container, it sets a column break immediately before. This might be used for an experimental design approach. </p> </div> </div> ); }
Breakpoint Modifiers
Tailwind's break-before-*
utilities can also be combined with the breakpoint modifiers to apply breaks only on specific screens and above. Use Tailwind's breakpoint modifiers like sm
, md
, lg
, etc. to apply this behavior.
export default function BreakpointsDemo() { return ( <div className="columns-1 h-screen w-screen p-8"> {/* Default no break applied */} <div className="bg-white p-6 mb-4"> <h2 className="text-2xl font-bold"> Universal Segment </h2> <p className="mt-2"> This container does not enforce a page or column break on any device. It's a standard block that flows naturally. </p> </div> {/* Add break on medium screens */} <div className="md:break-before-column bg-white p-6 mb-4"> <h2 className="text-2xl font-semibold"> Breaks on Medium Screens </h2> <p className="mt-2"> On medium size or larger screens, this will force a column break before it. On smaller devices, no break is applied, allowing continuous scrolling. </p> </div> {/* Break on large screens and above */} <div className="lg:break-before-column bg-white p-6 mb-4"> <h2 className="text-2xl font-semibold"> Breaks on Large Screens </h2> <p className="mt-2"> This class enforces a columns break on large screens. When previewed on large screens and beyond, this content shifts itself to a new column.</p> </div> {/* Following block for demonstration */} <div className="bg-white p-6"> <img src="https://images.unsplash.com/photo-1487017159836-4e23ece2e4cf" alt="Sample" className="rounded mb-4" /> <h2 className="text-xl font-medium"> Continuation </h2> <p className="mt-2"> This content comes after any enforced break, concluding how you can use responsive conditions to tailor breakpoints for different use cases. </p> </div> </div> ); }
Real World Examples
Product Catalog
A responsive product layout that breaks columns for better layout of an e-commerce catalog.
const ProductCatalog = () => { const products = [ { id: 1, name: "Leather Messenger Bag", price: "$129.99", category: "Accessories", src: "https://images.unsplash.com/photo-1553062407-98eeb64c6a62", alt: "Brown leather messenger bag" }, { id: 2, name: "Wireless Headphones", price: "$199.99", category: "Electronics", src: "https://images.unsplash.com/photo-1505740420928-5e560c06d30e", alt: "Black wireless headphones" }, { id: 3, name: "Minimalist Watch", price: "$89.99", category: "Accessories", src: "https://images.unsplash.com/photo-1523275335684-37898b6baf30", alt: "Simple black watch" }, { id: 4, name: "Smart Speaker", price: "$149.99", category: "Electronics", src: "https://images.unsplash.com/photo-1589492477829-5e65395b66cc", alt: "Black smart speaker" }, ]; return ( <div className="columns-1"> {products.map((product) => ( <div key={product.id} className="break-before-column border rounded-lg p-4 shadow-sm"> <img src={product.src} alt={product.alt} className="w-full h-48 object-cover rounded-md" /> <div className="mt-4"> <h3 className="font-semibold text-lg">{product.name}</h3> <p className="text-gray-600">{product.category}</p> <p className="text-blue-600 font-bold mt-2">{product.price}</p> </div> </div> ))} </div> ); }; export default ProductCatalog;
Blog Post Archive
A blog archive section that uses break-before-page
for clean printing of article sections.
const BlogArchive = () => { const blogPosts = [ { id: 1, title: "Understanding Modern Web Architecture", date: "2024-01-15", author: "Sarah Chen", excerpt: "An in-depth look at contemporary web architecture patterns...", category: "Technology", readTime: "8 min", src: "https://images.unsplash.com/photo-1517694712202-14dd9538aa97", alt: "Computer with code on screen" }, { id: 2, title: "The Future of Artificial Intelligence", date: "2024-01-18", author: "Michael Roberts", excerpt: "Exploring the upcoming trends in AI development...", category: "AI", readTime: "6 min", src: "https://images.unsplash.com/photo-1677442136019-21780ecad995", alt: "AI visualization" }, { id: 3, title: "Sustainable Software Practices", date: "2024-01-22", author: "Emma Thompson", excerpt: "Best practices for environmentally conscious development...", category: "Development", readTime: "5 min", src: "https://images.unsplash.com/photo-1623479322729-28b25c16b011", alt: "Green technology concept" }, { id: 4, title: "Mobile-First Design Principles", date: "2024-01-25", author: "David Kim", excerpt: "Essential guidelines for mobile-first development...", category: "Design", readTime: "7 min", src: "https://images.unsplash.com/photo-1512941937669-90a1b58e7e9c", alt: "Mobile devices display" }, { id: 5, title: "Cloud Computing Evolution", date: "2024-01-28", author: "Lisa Martinez", excerpt: "The transformation of cloud infrastructure...", category: "Cloud", readTime: "9 min", src: "https://images.unsplash.com/photo-1544197150-b99a580bb7a8", alt: "Cloud server room" }, { id: 6, title: "DevOps Best Practices", date: "2024-01-30", author: "James Wilson", excerpt: "Modern approaches to DevOps implementation...", category: "DevOps", readTime: "10 min", src: "https://images.unsplash.com/photo-1614741118887-7a4ee193a5fa", alt: "DevOps workflow diagram" } ]; return ( <div className="space-y-8 m-6"> {blogPosts.map((post) => ( <article key={post.id} className="break-before-page" > <div className="flex flex-col md:flex-row gap-6"> <img src={post.src} alt={post.alt} className="w-full md:w-72 h-48 object-cover rounded-lg" /> <div className="flex-1"> <div className="flex items-center gap-4 text-sm text-gray-600"> <span>{post.category}</span> <span>•</span> <span>{post.date}</span> <span>•</span> <span>{post.readTime}</span> </div> <h3 className="text-xl font-bold mt-2">{post.title}</h3> <p className="text-gray-600 mt-2">{post.excerpt}</p> <div className="mt-4"> <span className="text-sm font-medium">By {post.author}</span> </div> </div> </div> </article> ))} </div> ); }; export default BlogArchive;
Team Directory
A team directory layout that implements column breaks on every two employee cards.
const TeamDirectory = () => { const team = [ { id: 1, name: "Dr. Alexandra Chen", role: "Chief Research Officer", department: "Research & Development", email: "a.chen@company.com", location: "San Francisco, CA", src: "https://images.unsplash.com/photo-1573497019940-1c28c88b4f3e", alt: "Professional headshot of Dr. Chen" }, { id: 2, name: "Marcus Thompson", role: "Lead Software Architect", department: "Engineering", email: "m.thompson@company.com", location: "Seattle, WA", src: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e", alt: "Professional headshot of Marcus Thompson" }, { id: 3, name: "Dr. Sarah Williams", role: "Data Science Director", department: "Analytics", email: "s.williams@company.com", location: "Boston, MA", src: "https://images.unsplash.com/photo-1580489944761-15a19d654956", alt: "Professional headshot of Dr. Williams" }, { id: 4, name: "James Rodriguez", role: "UX Research Lead", department: "Design", email: "j.rodriguez@company.com", location: "Austin, TX", src: "https://images.unsplash.com/photo-1519085360753-af0119f7cbe7", alt: "Professional headshot of James Rodriguez" }, { id: 5, name: "Emily Parker", role: "Product Strategy Head", department: "Product", email: "e.parker@company.com", location: "New York, NY", src: "https://images.unsplash.com/photo-1573496359142-b8d87734a5a2", alt: "Professional headshot of Emily Parker" }, { id: 6, name: "Michael Chang", role: "Security Operations Director", department: "Information Security", email: "m.chang@company.com", location: "Chicago, IL", src: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d", alt: "Professional headshot of Michael Chang" } ]; return ( <div className="columns-1 gap-8"> {team.map((member, index) => ( <div key={member.id} className={`bg-white rounded-xl shadow-sm p-6 mb-6 ${index % 2 === 0 && index !== 0 ? 'break-before-column' : ''}`} > <div className="flex items-center space-x-4"> <img src={member.src} alt={member.alt} className="w-16 h-16 rounded-full object-cover" /> <div> <h3 className="font-semibold text-lg">{member.name}</h3> <p className="text-blue-600">{member.role}</p> </div> </div> <div className="mt-4 space-y-2 text-sm text-gray-600"> <p>📍 {member.location}</p> <p>🏢 {member.department}</p> <p>✉️ {member.email}</p> </div> </div> ))} </div> ); }; export default TeamDirectory;
Course Curriculum
A printable course curriculum layout that uses page breaks between different course sections.
const CourseCurriculum = () => { const courses = [ { id: 1, title: "Introduction to Machine Learning", instructor: "Dr. Emily Watson", duration: "8 weeks", level: "Intermediate", topics: ["Neural Networks", "Supervised Learning", "Model Evaluation"], prerequisites: ["Python", "Basic Statistics"], src: "https://images.unsplash.com/photo-1620712943543-bcc4688e7485", alt: "AI visualization concept", startDate: "February 1, 2024" }, { id: 2, title: "Advanced Web Development", instructor: "Prof. Michael Chen", duration: "10 weeks", level: "Advanced", topics: ["React", "Node.js", "GraphQL"], prerequisites: ["JavaScript", "HTML/CSS"], src: "https://images.unsplash.com/photo-1627398242454-45a1465c2479", alt: "Web development illustration", startDate: "February 15, 2024" }, { id: 3, title: "Cloud Architecture Fundamentals", instructor: "Sarah Martinez", duration: "6 weeks", level: "Beginner", topics: ["AWS", "Azure", "Cloud Security"], prerequisites: ["Basic Networking"], src: "https://images.unsplash.com/photo-1451187580459-43490279c0fa", alt: "Cloud computing concept", startDate: "March 1, 2024" }, { id: 4, title: "Data Science with Python", instructor: "Dr. James Wilson", duration: "12 weeks", level: "Intermediate", topics: ["Pandas", "NumPy", "Matplotlib"], prerequisites: ["Python Basics", "Statistics"], src: "https://images.unsplash.com/photo-1551288049-bebda4e38f71", alt: "Data visualization", startDate: "March 15, 2024" }, { id: 5, title: "Mobile App Development", instructor: "Lisa Thompson", duration: "10 weeks", level: "Intermediate", topics: ["React Native", "iOS", "Android"], prerequisites: ["JavaScript", "React"], src: "https://images.unsplash.com/photo-1512941937669-90a1b58e7e9c", alt: "Mobile development concept", startDate: "April 1, 2024" }, { id: 6, title: "Cybersecurity Essentials", instructor: "Robert Kim", duration: "8 weeks", level: "Beginner", topics: ["Network Security", "Cryptography", "Risk Management"], prerequisites: ["Basic IT Knowledge"], src: "https://images.unsplash.com/photo-1563986768609-322da13575f3", alt: "Cybersecurity concept", startDate: "April 15, 2024" } ]; return ( <div className="space-y-8 m-6"> {courses.map((course, index) => ( <div key={course.id} className={`bg-white rounded-lg shadow-sm ${index % 2 === 0 ? 'break-before-page' : ''}`} > <div className="flex flex-col md:flex-row border-2 border-black border-dashed rounded-lg"> <img src={course.src} alt={course.alt} className="h-48 md:w-72 object-cover " /> <div className="p-6"> <div className="flex items-center gap-4 text-sm text-gray-600"> <span className="px-3 py-1 bg-blue-100 text-blue-700 rounded-full">{course.level}</span> <span>{course.duration}</span> <span>Starts {course.startDate}</span> </div> <h3 className="text-xl font-bold mt-2">{course.title}</h3> <p className="text-gray-700 mt-1">Instructor: {course.instructor}</p> <div className="mt-4"> <h4 className="font-semibold text-gray-700">Topics Covered:</h4> <div className="flex flex-wrap gap-2 mt-2"> {course.topics.map((topic, i) => ( <span key={i} className="px-2 py-1 bg-gray-100 text-gray-700 rounded text-sm" > {topic} </span> ))} </div> </div> <div className="mt-4"> <h4 className="font-semibold text-gray-700">Prerequisites:</h4> <div className="flex flex-wrap gap-2 mt-2"> {course.prerequisites.map((prereq, i) => ( <span key={i} className="px-2 py-1 bg-yellow-50 text-yellow-700 rounded text-sm" > {prereq} </span> ))} </div> </div> </div> </div> </div> ))} </div> ); }; export default CourseCurriculum;
News Feed
A news feed where different news categories start on new lines using break-before-page
.
export default function NewsFeed() { const newsItems = [ { id: 1, category: "Technology", title: "Latest AI Breakthrough", excerpt: "Scientists develop new AI model that can understand complex patterns.", src: "https://images.unsplash.com/photo-1515378791036-0648a3ef77b2", alt: "AI technology visualization" }, { id: 2, category: "Technology", title: "5G Network Expansion", excerpt: "Major telecom companies announce nationwide 5G coverage plans.", src: "https://images.unsplash.com/photo-1519389950473-47ba0277781c", alt: "5G network tower" }, { id: 3, category: "Business", title: "Market Analysis Report", excerpt: "Global markets show signs of recovery in Q3 2023.", src: "https://images.unsplash.com/photo-1460925895917-afdab827c52f", alt: "Stock market charts" }, { id: 4, category: "Business", title: "Startup Funding News", excerpt: "Tech startups secure record funding in emerging markets.", src: "https://images.unsplash.com/photo-1553729459-efe14ef6055d", alt: "Startup office space" }, { id: 5, category: "Science", title: "Space Exploration Update", excerpt: "New discoveries from Mars rover mission announced.", src: "https://images.unsplash.com/photo-1446776811953-b23d57bd21aa", alt: "Mars surface photo" }, { id: 6, category: "Science", title: "Climate Research Findings", excerpt: "Latest study reveals impact of ocean warming on marine life.", src: "https://images.unsplash.com/photo-1437622368342-7a3d73a34c8f", alt: "Ocean ecosystem" } ]; return ( <div className="max-w-4xl mx-auto p-6"> {newsItems.map((item, index) => ( <article key={item.id} className={`mb-8 ${ index > 0 && newsItems[index - 1].category !== item.category ? 'break-before-page' : '' }`} > <div className="flex gap-6"> <img src={item.src} alt={item.alt} className="w-48 h-32 object-cover rounded-lg" /> <div> <span className="text-sm text-blue-600">{item.category}</span> <h2 className="text-xl font-bold mt-1">{item.title}</h2> <p className="text-gray-600 mt-2">{item.excerpt}</p> </div> </div> </article> ))} </div> ); }
Best Practices
Maintain Design Consistency
Applying the break-before-*
utility should align with the overall design structure to ensure a uniform and professional appearance across your project. Page breaks should be applied with intention, particularly when dealing with paginated content, print styles, or structured layouts such as reports and invoices. Without proper planning, inconsistencies in element positioning can lead to visual fragmentation, disrupting the flow of the interface.
One effective approach is to define a consistent set of page-break rules that correspond to different content types. For example, ensuring that headers always start on a new page using break-before-page
while keeping content sections on the same page whenever possible avoids unnecessary gaps. By keeping break rules uniform, readability and content structure remain predictable.
Optimize for Reusability
Reusable components provide an efficient way to standardize break-before-*
usage while keeping the project scalable. Instead of manually adding break utilities in different sections, abstract break logic into reusable layout components to simplify maintenance.
For example, a reusable ContentBlock
component that accepts breakBefore
as a prop ensures that different content sections can dictate their break behavior without modifying individual styles. By using this approach, you can dynamically modify break behavior while ensuring that styles remain consistent across different content sections.
Accessibility Considerations
Enhance Readability and Navigability
Content readability is a key consideration when using break-before-*
. Uncontrolled page breaks can disrupt the logical flow of text, making it harder for users—especially those with cognitive disabilities—to follow content. Ensuring that page breaks align with natural content divisions, such as heading transitions or major sections, improves accessibility.
When working with paginated layouts, it is important to maintain visual and contextual continuity between sections. For instance, avoid breaking inline content like lists or tables unnecessarily, as this can hinder comprehension. Instead, focus on breaking before significant headings or groups of related elements.
Support Accessible Interactive Elements
When applying break-before-*
to components that contain interactive elements, such as buttons, forms, or navigation links, consider how breaks impact usability. For instance, splitting an interactive form across a forced break can disrupt the user experience, making it harder to complete actions efficiently.
To enhance accessibility, avoid using break-before-*
in ways that fragment interactive workflows. If a section contains form inputs or navigation items, ensure that breaks do not separate related components.