<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="https://publishpress.com/"
	>

<channel>
	<title>Thang Dang, Author at Tomoshare</title>
	<atom:link href="https://blog.tomosia.com.vn/author/thang-dang/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.tomosia.com.vn/author/thang-dang/</link>
	<description>Kênh chia sẻ kiến thức Tomosia Việt Nam</description>
	<lastBuildDate>Fri, 22 May 2026 07:28:24 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://blog.tomosia.com.vn/wp-content/uploads/2023/09/cropped-icon-32x32.png</url>
	<title>Thang Dang, Author at Tomoshare</title>
	<link>https://blog.tomosia.com.vn/author/thang-dang/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Tại sao position: sticky của bạn không hoạt động ?</title>
		<link>https://blog.tomosia.com.vn/tai-sao-position-sticky-cua-ban-khong-hoat-dong/</link>
					<comments>https://blog.tomosia.com.vn/tai-sao-position-sticky-cua-ban-khong-hoat-dong/#respond</comments>
		
		<dc:creator><![CDATA[Thang Dang]]></dc:creator>
		<pubDate>Fri, 22 May 2026 07:28:21 +0000</pubDate>
				<category><![CDATA[Html/CSS]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=3952</guid>

					<description><![CDATA[<p>Position: sticky là một trong những thuộc tính CSS mạnh mẽ, dùng trong nhiều trường hợp để nội&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/tai-sao-position-sticky-cua-ban-khong-hoat-dong/">Tại sao position: sticky của bạn không hoạt động ?</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Position: sticky là một trong những thuộc tính CSS mạnh mẽ, dùng trong nhiều trường hợp để nội dung được hoạt động xuyên suốt nhưng cũng rất dễ &#8220;không hoạt động&#8221; nếu hiểu sai bản chất</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 id="1-position-sticky-hoat-dong-nhu-the-nao" class="wp-block-heading">1. <code>position: sticky</code> hoạt động như thế nào?</h2>



<p class="wp-block-paragraph">Một element có <code>position: sticky</code> sẽ:</p>



<ol class="wp-block-list">
<li><strong>Hoạt động như <code>position: relative</code></strong> cho đến khi</li>



<li><strong>Một cạnh</strong> (<code>top</code> / <code>bottom</code> / <code>left</code> / <code>right</code>) <strong>chạm tới offset</strong> đã chỉ định trong vùng scroll</li>



<li>Sau đó nó sẽ <strong>&#8220;dính&#8221; (stick)</strong> tại vị trí đó</li>
</ol>



<p class="wp-block-paragraph">📌 <strong>Quan trọng</strong>: Sticky luôn bị giới hạn trong phạm vi của parent (không vượt ra ngoài).</p>



<h3 id="vi-du-minh-hoa" class="wp-block-heading">Ví dụ minh họa</h3>



<pre class="wp-block-code"><code>.header {
  position: sticky;
  top: 0;
  background: white;
  z-index: 10;
}</code></pre>



<p class="wp-block-paragraph">Header này sẽ cuộn bình thường cho đến khi cạnh trên chạm vị trí <code>0px</code> từ đỉnh viewport, sau đó sẽ &#8220;dính&#8221; lại ở đó khi bạn tiếp tục cuộn xuống.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 id="2-dieu-kien-bat-buoc-de-sticky-hoat-dong" class="wp-block-heading">2. Điều kiện bắt buộc để sticky hoạt động</h2>



<h3 id="2-1-phai-co-it-nhat-mot-offset" class="wp-block-heading">2.1. Phải có ít nhất một offset</h3>



<p class="wp-block-paragraph">❌ <strong>Sai:</strong></p>



<pre class="wp-block-code"><code>.sticky {
  position: sticky;
}
</code></pre>



<p class="wp-block-paragraph">✅ <strong>Đúng:</strong></p>



<pre class="wp-block-code"><code>.sticky {
  position: sticky;
  top: 0;
}
</code></pre>



<p class="wp-block-paragraph"><strong>Tailwind CSS:</strong></p>



<pre class="wp-block-code"><code>&lt;div class="sticky top-0"&gt;...&lt;/div&gt;
</code></pre>



<h3 id="2-2-parent-khong-duoc-co-overflow-hidden-auto-scroll" class="wp-block-heading">2.2. Parent không được có <code>overflow: hidden | auto | scroll</code></h3>



<p class="wp-block-paragraph">Nếu bất kỳ cha nào có <code>overflow</code> khác <code>visible</code> → sticky bị vô hiệu hóa.</p>



<p class="wp-block-paragraph">❌ <strong>Sai:</strong></p>



<pre class="wp-block-code"><code>.parent {
  overflow: hidden;
}</code></pre>



<p class="wp-block-paragraph">✅ <strong>Fix:</strong></p>



<ul class="wp-block-list">
<li>Xoá <code>overflow</code></li>



<li>Hoặc đưa sticky ra ngoài container đó</li>



<li>Hoặc áp dụng <code>overflow</code> cho một container bên trong</li>
</ul>



<h3 id="2-3-parent-phai-du-cao-de-co-scroll" class="wp-block-heading">2.3. Parent phải đủ cao để có scroll</h3>



<p class="wp-block-paragraph">Sticky chỉ kích hoạt khi có scroll thật.</p>



<p class="wp-block-paragraph">❌ <strong>Sai:</strong></p>



<pre class="wp-block-code"><code>&lt;div style="height: 100px">
  &lt;div class="sticky">Short parent&lt;/div>
&lt;/div></code></pre>



<p class="wp-block-paragraph">✅ <strong>Đúng:</strong></p>



<pre class="wp-block-code"><code>&lt;div style="min-height: 200vh">
  &lt;div class="sticky">Tall parent&lt;/div>
&lt;/div></code></pre>



<h3 id="2-4-parent-khong-duoc-dung-transform" class="wp-block-heading">2.4. Parent không được dùng <code>transform</code></h3>



<p class="wp-block-paragraph">Nếu parent có:</p>



<ul class="wp-block-list">
<li><code>transform: translateZ(0);</code></li>



<li><code>transform: scale(1);</code></li>



<li>hoặc animation/transition với transform</li>
</ul>



<p class="wp-block-paragraph">→ sticky không hoạt động.</p>



<p class="wp-block-paragraph"><strong>Giải pháp</strong>: Di chuyển transform ra khỏi parent, hoặc áp dụng cho element khác.</p>



<h3 id="2-5-z-index-co-the-lam-ban-tuong-sticky-khong-chay" class="wp-block-heading">2.5. <code>z-index</code> có thể làm bạn tưởng sticky không chạy</h3>



<p class="wp-block-paragraph">Sticky vẫn hoạt động nhưng bị che bởi các element khác.</p>



<pre class="wp-block-code"><code>.sticky {
  position: sticky;
  top: 0;
  z-index: 10;
  background: white; /* Quan trọng để không bị trong suốt */
}
</code></pre>



<p class="wp-block-paragraph"><strong>Tailwind CSS:</strong></p>



<pre class="wp-block-code"><code>&lt;div class="sticky top-0 z-10 bg-white"&gt;...&lt;/div&gt;
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 id="3-vi-sao-top-30px-khong-hoat-dong-nhung-bottom-30px-lai-duoc" class="wp-block-heading">3. Vì sao <code>top: 30px</code> không hoạt động nhưng <code>bottom: 30px</code> lại được?</h2>



<p class="wp-block-paragraph">Đây là bẫy rất phổ biến và gây nhầm lẫn nhiều nhất.</p>



<h3 id="nguyen-nhan-cot-loi" class="wp-block-heading">Nguyên nhân cốt lõi</h3>



<p class="wp-block-paragraph">Sticky chỉ hoạt động nếu <strong>cạnh được chỉ định CÓ KHẢ NĂNG chạm tới offset đó khi scroll</strong>.</p>



<ul class="wp-block-list">
<li><code>top: 30px</code> → cạnh trên phải chạm 30px từ đỉnh vùng scroll</li>



<li><code>bottom: 30px</code> → cạnh dưới phải chạm 30px từ đáy vùng scroll</li>
</ul>



<p class="wp-block-paragraph">👉 <strong>Trong layout của bạn:</strong></p>



<ul class="wp-block-list">
<li>Cạnh trên không bao giờ chạm được 30px → <code>top</code> không hoạt động</li>



<li>Nhưng cạnh dưới có thể chạm → <code>bottom</code> hoạt động</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 id="4-cac-tinh-huong-gay-ra-hien-tuong-nay" class="wp-block-heading">4. Các tình huống gây ra hiện tượng này</h2>



<h3 id="4-1-element-da-nam-san-gan-top-parent" class="wp-block-heading">4.1. Element đã nằm sẵn gần top parent</h3>



<pre class="wp-block-code"><code>&lt;div class="parent">
  &lt;div class="sticky" style="position: sticky; top: 30px">
    Tôi đã nằm ở đây từ đầu
  &lt;/div>
&lt;/div></code></pre>



<p class="wp-block-paragraph"><strong>Phân tích:</strong></p>



<ul class="wp-block-list">
<li>Nếu sticky ban đầu đã nằm ≤ 30px từ top</li>



<li><code>top: 30px</code> → không có thời điểm kích hoạt</li>



<li>Browser coi như <code>position: relative</code></li>
</ul>



<p class="wp-block-paragraph"><strong>Trong khi đó:</strong></p>



<ul class="wp-block-list">
<li>Khi scroll, cạnh dưới vẫn có thể chạm đáy viewport</li>



<li>→ <code>bottom</code> hoạt động bình thường</li>
</ul>



<h3 id="4-2-parent-khong-du-cao" class="wp-block-heading">4.2. Parent không đủ cao</h3>



<p class="wp-block-paragraph">Sticky bị giới hạn trong parent.</p>



<ul class="wp-block-list">
<li>Khoảng cách từ sticky → đỉnh parent quá ngắn → <code>top</code> không kích hoạt</li>



<li>Khoảng cách tới đáy parent vẫn còn → <code>bottom</code> hoạt động</li>
</ul>



<pre class="wp-block-code"><code>&lt;div style="height: 200px"> &lt;!-- Parent quá ngắn -->
  &lt;div style="position: sticky; top: 30px">
    Không đủ khoảng cách để stick
  &lt;/div>
&lt;/div></code></pre>



<h3 id="4-3-scroll-container-khong-phai-window" class="wp-block-heading">4.3. Scroll container không phải window</h3>



<pre class="wp-block-code"><code>.wrapper {
  height: 100vh;
  overflow-y: auto;
}</code></pre>



<p class="wp-block-paragraph"><code>top</code> được tính theo <code>.wrapper</code>, không phải theo màn hình.</p>



<p class="wp-block-paragraph">Nếu sticky đã gần top của wrapper → <code>top</code> không ăn.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 id="5-minh-hoa-truc-quan" class="wp-block-heading">5. Minh họa trực quan</h2>



<h3 id="top-khong-hoat-dong" class="wp-block-heading"><code>top</code> không hoạt động</h3>



<pre class="wp-block-code"><code>┌─────────────┐
│  viewport   │
│             │
│   30px ↓    │ ← Mốc sticky mong muốn
│  &#91;sticky]   │ ← Nhưng element đã nằm sẵn ở đây
│   content   │
│      ⋮      │
└─────────────┘
</code></pre>



<p class="wp-block-paragraph"><strong>Không có lúc nào cạnh trên chạm mốc 30px</strong> → Sticky không kích hoạt</p>



<h3 id="bottom-hoat-dong" class="wp-block-heading"><code>bottom</code> hoạt động</h3>



<pre class="wp-block-code"><code>┌─────────────┐
│   content   │
│      ⋮      │
│  &#91;sticky]   │ ← Element bắt đầu ở đây
│             │
│   30px ↑    │ ← Khi scroll, cạnh dưới sẽ chạm mốc này
│  viewport   │
└─────────────┘
</code></pre>



<p class="wp-block-paragraph"><strong>Cạnh dưới có lúc chạm 30px</strong> → Sticky kích hoạt</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 id="6-cach-fix-top-30px-khong-hoat-dong" class="wp-block-heading">6. Cách fix <code>top: 30px</code> không hoạt động</h2>



<h3 id="%e2%9c%85-cach-1-tao-khoang-cach-ban-dau" class="wp-block-heading">✅ Cách 1: Tạo khoảng cách ban đầu</h3>



<pre class="wp-block-code"><code>.sticky {
  margin-top: 40px; /* Đẩy xuống để có khoảng cách */
  position: sticky;
  top: 30px;
}</code></pre>



<h3 id="%e2%9c%85-cach-2-dat-sticky-thap-hon-trong-dom" class="wp-block-heading">✅ Cách 2: Đặt sticky thấp hơn trong DOM</h3>



<pre class="wp-block-code"><code>&lt;div class="parent">
  &lt;div style="height: 100px">&lt;/div> &lt;!-- Spacer -->
  &lt;div class="sticky" style="position: sticky; top: 30px">
    Bây giờ có khoảng cách để stick
  &lt;/div>
&lt;/div></code></pre>



<h3 id="%e2%9c%85-cach-3-kiem-tra-overflow-cua-parent" class="wp-block-heading">✅ Cách 3: Kiểm tra overflow của parent</h3>



<pre class="wp-block-code"><code>.parent {
  overflow: visible; /* Hoặc bỏ hoàn toàn */
}</code></pre>



<h3 id="%e2%9c%85-cach-4-debug-nhanh-bang-outline" class="wp-block-heading">✅ Cách 4: Debug nhanh bằng outline</h3>



<pre class="wp-block-code"><code>.sticky {
  position: sticky;
  top: 30px;
  outline: 2px solid red; /* Giúp nhìn rõ khi nào sticky kích hoạt */
}</code></pre>



<p class="wp-block-paragraph">Khi bạn scroll, nếu outline màu đỏ &#8220;dính&#8221; lại ở vị trí 30px từ trên xuống, nghĩa là sticky đã hoạt động.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 id="7-checklist-debug-sticky-90-fix-duoc-van-de" class="wp-block-heading">7. Checklist debug sticky (90% fix được vấn đề)</h2>



<p class="wp-block-paragraph">Khi sticky không hoạt động, hãy check theo thứ tự:</p>



<ul class="wp-block-list">
<li>✔ <strong>Có <code>top</code> / <code>bottom</code> / <code>left</code> / <code>right</code></strong> được khai báo?</li>



<li>✔ <strong>Parent không có <code>overflow: hidden/auto/scroll</code></strong>?</li>



<li>✔ <strong>Có scroll thật</strong> (parent đủ cao)?</li>



<li>✔ <strong>Parent không dùng <code>transform</code></strong>?</li>



<li>✔ <strong>Có <code>z-index</code> và <code>background</code></strong> nếu cần?</li>



<li>✔ <strong>Cạnh được chỉ định có khả năng chạm offset</strong> không?</li>
</ul>



<h3 id="debug-tool-nhanh" class="wp-block-heading">Debug tool nhanh</h3>



<pre class="wp-block-code"><code>/* Thêm vào element sticky để debug */
.sticky {
  outline: 3px dashed red;
  outline-offset: -3px;
}

/* Thêm vào parent để kiểm tra */
.parent {
  outline: 2px solid blue;
}</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 id="8-vi-du-thuc-te-sticky-header" class="wp-block-heading">8. Ví dụ thực tế: Sticky header</h2>



<h3 id="%e2%9d%8c-khong-hoat-dong" class="wp-block-heading">❌ Không hoạt động</h3>



<pre class="wp-block-code"><code>&lt;div style="overflow: hidden"> &lt;!-- Lỗi: overflow -->
  &lt;header style="position: sticky; top: 0">
    Menu
  &lt;/header>
  &lt;main>Content...&lt;/main>
&lt;/div></code></pre>



<h3 id="%e2%9c%85-hoat-dong-dung" class="wp-block-heading">✅ Hoạt động đúng</h3>



<pre class="wp-block-code"><code>&lt;div> &lt;!-- Không có overflow -->
  &lt;header style="position: sticky; top: 0; z-index: 10; background: white">
    Menu
  &lt;/header>
  &lt;main style="min-height: 200vh">
    Content...
  &lt;/main>
&lt;/div></code></pre>



<h3 id="voi-tailwind-css" class="wp-block-heading">Với Tailwind CSS</h3>



<pre class="wp-block-code"><code>&lt;div>
  &lt;header class="sticky top-0 z-10 bg-white shadow">
    &lt;nav class="container mx-auto">Menu&lt;/nav>
  &lt;/header>
  &lt;main class="min-h-&#91;200vh]">
    Content...
  &lt;/main>
&lt;/div></code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 id="9-vi-du-nang-cao-sticky-sidebar" class="wp-block-heading">9. Ví dụ nâng cao: Sticky sidebar</h2>



<pre class="wp-block-code"><code>&lt;div class="flex gap-4">
  &lt;!-- Sidebar sticky -->
  &lt;aside class="w-64">
    &lt;div class="sticky top-4">
      &lt;nav>Navigation links...&lt;/nav>
    &lt;/div>
  &lt;/aside>
  
  &lt;!-- Main content -->
  &lt;main class="flex-1 min-h-&#91;200vh]">
    Long content...
  &lt;/main>
&lt;/div></code></pre>



<p class="wp-block-paragraph"><strong>Tailwind CSS:</strong></p>



<pre class="wp-block-code"><code>&lt;div class="flex gap-4">
  &lt;aside class="w-64">
    &lt;div class="sticky top-4">
      &lt;nav>Navigation&lt;/nav>
    &lt;/div>
  &lt;/aside>
  &lt;main class="flex-1 min-h-&#91;200vh]">Content&lt;/main>
&lt;/div></code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 id="10-luu-y-khi-dung-voi-framework" class="wp-block-heading">10. Lưu ý khi dùng với framework</h2>



<h3 id="nuxt-vue" class="wp-block-heading">Nuxt / Vue</h3>



<pre class="wp-block-code"><code>&lt;template>
  &lt;div class="container">
    &lt;!-- ❌ Tránh -->
    &lt;div style="overflow-x: hidden">
      &lt;header class="sticky top-0">Header&lt;/header>
    &lt;/div>
    
    &lt;!-- ✅ Đúng -->
    &lt;header class="sticky top-0 z-10 bg-white">Header&lt;/header>
  &lt;/div>
&lt;/template>

&lt;style scoped>
.container {
  /* Không dùng overflow ở đây */
}
&lt;/style></code></pre>



<h3 id="react-next-js" class="wp-block-heading">React / Next.js</h3>



<pre class="wp-block-code"><code>export default function Layout({ children }) {
  return (
    &lt;div className="min-h-screen">
      &lt;header className="sticky top-0 z-10 bg-white shadow">
        &lt;nav>Menu&lt;/nav>
      &lt;/header>
      &lt;main className="container mx-auto">
        {children}
      &lt;/main>
    &lt;/div>
  )
}</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 id="11-ket-luan" class="wp-block-heading">11. Kết luận</h2>



<p class="wp-block-paragraph"><code>position: sticky</code> không hề lỗi, chỉ là nó rất <strong>nghiêm ngặt về điều kiện kích hoạt</strong>.</p>



<h3 id="nguyen-tac-vang" class="wp-block-heading">Nguyên tắc vàng</h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>&#8220;Cạnh này có thực sự chạm được offset đó khi scroll không?&#8221;</strong></p>
</blockquote>



<p class="wp-block-paragraph">Nếu <code>top</code> không hoạt động nhưng <code>bottom</code> lại được, <strong>99% là do cạnh trên không bao giờ chạm được offset đã chỉ định</strong>.</p>



<h3 id="loi-khuyen-cuoi" class="wp-block-heading">Lời khuyên cuối</h3>



<ul class="wp-block-list">
<li>Nếu bạn đang dùng <strong>Nuxt / Tailwind / layout phức tạp</strong>, chỉ cần sai 1 class <code>overflow-hidden</code> là sticky hỏng hoàn toàn</li>



<li>Luôn test sticky với <strong>outline</strong> hoặc <strong>background màu nổi</strong> để debug</li>



<li>Đọc kỹ các điều kiện ở phần 2, đặc biệt là <strong>overflow</strong> và <strong>transform</strong></li>



<li>Khi gặp lỗi, check lại <strong>chiều cao parent</strong> và <strong>vị trí ban đầu</strong> của element</li>
</ul>



<p class="wp-block-paragraph">💡 <strong>Pro tip</strong>: Tạo một component/utility class sticky chuẩn cho project và tái sử dụng, tránh phải debug nhiều lần.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Chúc bạn code vui! 🚀</strong></p>
<p>The post <a href="https://blog.tomosia.com.vn/tai-sao-position-sticky-cua-ban-khong-hoat-dong/">Tại sao position: sticky của bạn không hoạt động ?</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/tai-sao-position-sticky-cua-ban-khong-hoat-dong/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
