<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vanessa Duarte</title>
    <description>The latest articles on DEV Community by Vanessa Duarte (@codewithvanessa).</description>
    <link>https://dev.to/codewithvanessa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4203357%2F2b7bda25-3a48-4eb2-911d-6fcb029fba4a.jpg</url>
      <title>DEV Community: Vanessa Duarte</title>
      <link>https://dev.to/codewithvanessa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codewithvanessa"/>
    <language>en</language>
    <item>
      <title>What I Learned Fixing Horizontal Overflow in a Next.js Dashboard</title>
      <dc:creator>Vanessa Duarte</dc:creator>
      <pubDate>Mon, 26 Oct 2026 21:42:04 +0000</pubDate>
      <link>https://dev.to/codewithvanessa/what-i-learned-fixing-horizontal-overflow-in-a-nextjs-dashboard-4dm1</link>
      <guid>https://dev.to/codewithvanessa/what-i-learned-fixing-horizontal-overflow-in-a-nextjs-dashboard-4dm1</guid>
      <description>&lt;p&gt;While preparing NovaSaaS for its first public release, I noticed a small but frustrating problem: the dashboard had horizontal and vertical page scrollbars that should not have been there.&lt;/p&gt;

&lt;p&gt;The issue was more visible after deploying the project to Netlify. The notification badge in the header was partially cut off, the page could move horizontally by a few pixels, and the entire document was scrolling instead of keeping the scrolling inside the dashboard content.&lt;/p&gt;

&lt;p&gt;At first, it looked like a simple CSS problem. It was actually a combination of several layout details: an incorrectly positioned notification badge, flex children that were not allowed to shrink, and a dashboard shell without strict viewport and overflow constraints.&lt;/p&gt;

&lt;p&gt;In this article, I will explain how I identified those problems, how I fixed them with Next.js and Tailwind CSS, and what I learned while testing the dashboard across different screen sizes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxoxaiblhg459hydw5rnd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxoxaiblhg459hydw5rnd.png" alt="![NovaSaaS dashboard showing workspace metrics, revenue and subscription charts, recent activity, and a collapsible navigation sidebar](https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/wwvgdq2yxwgw5wn9iuiu.png)" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The original layout problem
&lt;/h2&gt;

&lt;p&gt;NovaSaaS uses a typical admin dashboard structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A fixed sidebar on desktop&lt;/li&gt;
&lt;li&gt;A drawer-style navigation menu on mobile&lt;/li&gt;
&lt;li&gt;A header with breadcrumbs, search, notifications, and a user menu&lt;/li&gt;
&lt;li&gt;A main content area that contains the dashboard pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The desired behavior was simple: the dashboard shell should always fit inside the viewport, while the main content and sidebar navigation should scroll independently when necessary.&lt;/p&gt;

&lt;p&gt;Instead, the document itself was becoming wider and taller than the viewport.&lt;/p&gt;

&lt;p&gt;One useful check was comparing the document width with the visible viewport:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference was only a few pixels, but that was enough to create horizontal movement. After inspecting the elements near the right edge of the page, I found that the notification badge was extending outside the viewport.&lt;/p&gt;

&lt;p&gt;The vertical scrolling problem had a different cause. The dashboard used a flexible layout, but some of its children did not have the constraints required to shrink correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Constraining the dashboard shell
&lt;/h2&gt;

&lt;p&gt;The first change was to give the entire dashboard a fixed viewport height and prevent it from becoming the page-level scrolling container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-background flex h-dvh w-full overflow-hidden"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Sidebar&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex min-h-0 min-w-0 flex-1 flex-col"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DashboardHeader&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"main-content"&lt;/span&gt;
      &lt;span class="na"&gt;tabIndex&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"min-h-0 min-w-0 flex-1 overflow-y-auto overscroll-y-contain"&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used &lt;code&gt;h-dvh&lt;/code&gt; instead of &lt;code&gt;min-h-screen&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A minimum height allows the container to grow beyond the viewport when one of its children needs more space. In this case, I wanted the dashboard shell to remain exactly as tall as the available viewport.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;dvh&lt;/code&gt; also works better with mobile browser interfaces because it follows changes in the dynamic viewport height.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;overflow-hidden&lt;/code&gt; class prevents the shell itself from creating document-level scrollbars. Scrolling is then assigned explicitly to the content area with &lt;code&gt;overflow-y-auto&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why &lt;code&gt;min-h-0&lt;/code&gt; and &lt;code&gt;min-w-0&lt;/code&gt; matter
&lt;/h2&gt;

&lt;p&gt;The most important detail in this fix was not &lt;code&gt;overflow-hidden&lt;/code&gt;. It was adding &lt;code&gt;min-h-0&lt;/code&gt; and &lt;code&gt;min-w-0&lt;/code&gt; to the correct flex children.&lt;/p&gt;

&lt;p&gt;Flex items use an automatic minimum size by default. This can prevent them from shrinking below the size of their content, even when the parent has limited space.&lt;/p&gt;

&lt;p&gt;In a horizontal layout, &lt;code&gt;min-w-0&lt;/code&gt; allows the content area to shrink without pushing the layout beyond the viewport.&lt;/p&gt;

&lt;p&gt;In a vertical flex column, &lt;code&gt;min-h-0&lt;/code&gt; allows the scrollable child to stay within the remaining height instead of making the parent taller.&lt;/p&gt;

&lt;p&gt;This is why the main dashboard column uses both:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex min-h-0 min-w-0 flex-1 flex-col"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The scrollable content area also uses both constraints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;min-h-0 min-w-0 flex-1 overflow-y-auto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before this project, I knew these utilities individually, but this problem helped me understand how important they are when nested flex layouts include their own scrolling regions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anchoring the notification badge correctly
&lt;/h2&gt;

&lt;p&gt;The horizontal overflow came from the notification badge.&lt;/p&gt;

&lt;p&gt;The badge was absolutely positioned, but its positioning context was too large. At some desktop sizes, it extended a few pixels beyond the right side of the viewport.&lt;/p&gt;

&lt;p&gt;The fix was to make the bell icon and badge share a small relative container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
  &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ghost"&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt;
  &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;unread&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`Notifications, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;unreadLabel&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; unread`&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Notifications&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"relative inline-flex"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Bell&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"size-4"&lt;/span&gt; &lt;span class="na"&gt;aria-hidden&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;unread&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;
        &lt;span class="na"&gt;aria-hidden&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-primary text-primary-foreground pointer-events-none absolute -top-1 -right-1 flex min-h-4 min-w-4 items-center justify-center rounded-full px-1 text-[10px] leading-none font-semibold"&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;unreadLabel&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the badge is positioned relative to the bell instead of a larger header container.&lt;/p&gt;

&lt;p&gt;I also limited large notification counts to &lt;code&gt;99+&lt;/code&gt; so the badge cannot continue growing indefinitely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unreadLabel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unread&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;99+&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unread&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The button receives an accessible label with the unread count, while the visual badge is hidden from assistive technology to avoid announcing the same information twice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Giving the sidebar its own scroll
&lt;/h2&gt;

&lt;p&gt;The sidebar had to remain the same height as the dashboard while still supporting navigation lists that might become longer in future versions.&lt;/p&gt;

&lt;p&gt;The desktop sidebar is constrained to the dynamic viewport height:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;aside&lt;/span&gt;
  &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;cn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bg-sidebar relative hidden h-dvh shrink-0 border-r transition-[width] duration-200 lg:flex lg:flex-col&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;collapsed&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;w-20&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;w-64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside it, only the navigation section scrolls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;
  &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Primary"&lt;/span&gt;
  &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"-mx-1 min-h-0 min-w-0 flex-1 space-y-6 overflow-x-hidden overflow-y-auto overscroll-contain px-1"&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps the logo, organization switcher, version number, and collapse button in predictable positions while allowing the navigation links to scroll independently.&lt;/p&gt;

&lt;p&gt;For the mobile drawer, I used &lt;code&gt;h-dvh&lt;/code&gt;, &lt;code&gt;max-h-dvh&lt;/code&gt;, and a width that leaves some of the viewport visible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;aside&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-sidebar relative z-10 h-dvh max-h-dvh w-[min(18rem,calc(100vw-2rem))] border-r"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The drawer closes when the user selects a navigation link, clicks the backdrop, or presses Escape.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the header shrink safely
&lt;/h2&gt;

&lt;p&gt;The header contains several elements competing for horizontal space. The breadcrumbs, command menu, notification button, and user menu all behave differently as the viewport becomes narrower.&lt;/p&gt;

&lt;p&gt;The main header groups use &lt;code&gt;min-w-0&lt;/code&gt;, while controls that should preserve their size use &lt;code&gt;shrink-0&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex h-16 min-w-0 items-center gap-3 px-4 lg:px-8"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hidden min-w-0 flex-1 md:block"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Breadcrumbs&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ml-auto flex min-w-0 flex-1 items-center justify-end gap-2 md:flex-none"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"w-36 min-w-0 flex-1 sm:w-48 md:w-60 md:flex-none"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CommandMenu&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex shrink-0 items-center gap-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NotificationsPreview&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserMenu&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows the command menu to become narrower on small screens without pushing the notification and user controls outside the viewport.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the result
&lt;/h2&gt;

&lt;p&gt;After applying the fixes, I tested the dashboard at widths ranging from 320px to 1920px.&lt;/p&gt;

&lt;p&gt;I checked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Document-level horizontal and vertical overflow&lt;/li&gt;
&lt;li&gt;Expanded and collapsed desktop sidebar states&lt;/li&gt;
&lt;li&gt;Sidebar preference persistence&lt;/li&gt;
&lt;li&gt;Mobile drawer opening and closing&lt;/li&gt;
&lt;li&gt;Notification badge and dropdown positioning&lt;/li&gt;
&lt;li&gt;Main-content scrolling&lt;/li&gt;
&lt;li&gt;Sidebar navigation scrolling&lt;/li&gt;
&lt;li&gt;Light and dark themes&lt;/li&gt;
&lt;li&gt;Keyboard navigation and accessible labels&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The document width remained equal to the viewport width, and short dashboard pages no longer created document-level vertical scrolling. When content or navigation exceeded the available height, only the intended internal region scrolled.&lt;/p&gt;

&lt;p&gt;I also added regression tests for the sidebar layout and notification counts. They do not replace browser testing, but they help protect the expected structure and behavior from future changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;The main lesson was that overflow problems are often caused by several small layout decisions rather than one obviously incorrect style.&lt;/p&gt;

&lt;p&gt;These&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>tailwindcss</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
