PageSourceSearch

https://johnnywang1994.github.io/book/assets/landscape-fix-scroll.html-BgK9ufiV.js

js johnnywang1994.github.io collected 2026-10-03 09:24:41 UTC 17,066 bytes, 51 lines download raw bytes

1import{_ as t,c as l,b as n,d as a,a as p,e as c,r as i,o}from"./app-BgYE7jZN.js";const u={};function d(r,s){const e=i("SocialBlock");return o(),l("div",null,[s[0]||(s[0]=n("h1",{id:"css-畫面鎖橫屏時-滾動的問題",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#css-畫面鎖橫屏時-滾動的問題"},[n("span",null,"CSS 畫面鎖橫屏時,滾動的問題!!")])],-1)),s[1]||(s[1]=n("h6",{id:"tag-css-overflow-landscape",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#tag-css-overflow-landscape"},[n("span",null,[a("tag "),n("code",null,"css"),a(", "),n("code",null,"overflow"),a(", "),n("code",null,"landscape")])])],-1)),p(e,{hashtags:"css,overflow,landscape"}),s[2]||(s[2]=c(`<p>今天這篇主要紀錄日常開發上遇到的一個問題,那就是究竟要怎麼在畫面鎖橫屏的同時,又能讓瀏覽器的滾動事件正確的執行呢?</p><h2 id="問題重現" tabindex="-1"><a class="header-anchor" href="#問題重現"><span>問題重現</span></a></h2><p>在解決問題前,我們必須先重現問題,請將下方的程式碼輸入到您的瀏覽器中。</p><p>(建議可以用手機打開看看)</p><div class="language-html line-numbers-mode" data-highlighter="prismjs" data-ext="html"><pre><code class="language-html"><span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>app<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span></span>
2<span class="line">  Hello World</span>
3<span class="line">  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>box<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span></span>
4<span class="line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span></span>
5<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-scss line-numbers-mode" data-highlighter="prismjs" data-ext="scss"><pre><code class="language-scss"><span class="line"><span class="token selector">html </span><span class="token punctuation">{</span></span>
6<span class="line">  <span class="token comment">// 這邊因為轉向的關係,不能寫死寬高的 % 數,因為 % 數仍是依循 window 的寬高。</span></span>
7<span class="line">  <span class="token comment">// 必須讓畫面的寬是畫面長邊</span></span>
8<span class="line">  <span class="token property">width</span><span class="token punctuation">:</span> 100vmax<span class="token punctuation">;</span></span>
9<span class="line">  <span class="token property">overflow</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span> <span class="token comment">// 穿透 html 來滾動到 #app</span></span>
10<span class="line">  <span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">orientation</span><span class="token punctuation">:</span> portrait<span class="token punctuation">)</span></span> <span class="token punctuation">{</span></span>
11<span class="line">    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">rotate</span><span class="token punctuation">(</span>90deg<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
12<span class="line">    <span class="token property">transform-origin</span><span class="token punctuation">:</span> 50vmin 50vmin<span class="token punctuation">;</span></span>
13<span class="line">  <span class="token punctuation">}</span></span>
14<span class="line">  <span class="token selector">body </span><span class="token punctuation">{</span></span>
15<span class="line">    <span class="token property">margin</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span></span>
16<span class="line">  <span class="token punctuation">}</span></span>
17<span class="line"><span class="token punctuation">}</span></span>
18<span class="line"></span>
19<span class="line"><span class="token selector">#app </span><span class="token punctuation">{</span></span>
20<span class="line">  <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span></span>
21<span class="line">  <span class="token property">height</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span></span>
22<span class="line">  <span class="token property">overflow</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span> <span class="token comment">// 希望滾動我們的 #app</span></span>
23<span class="line">  <span class="token selector">.box </span><span class="token punctuation">{</span></span>
24<span class="line">    <span class="token property">height</span><span class="token punctuation">:</span>
24 1000px<span class="token punctuation">;</span></span>
25<span class="line">    <span class="token property">background</span><span class="token punctuation">:</span> lightblue<span class="token punctuation">;</span></span>
26<span class="line">  <span class="token punctuation">}</span></span>
27<span class="line"><span class="token punctuation">}</span></span>
28<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>我們對 html 設置 css @media 的轉向設定,可以讓畫面在直屏時,將畫面轉向 90 度達到橫屏的效果,但這邊就會發生一個問題,此時如果我們滾動畫面,就會發現實際上滾動還是直的!!</p><p>到底為什麼??</p><h2 id="分析問題" tabindex="-1"><a class="header-anchor" href="#分析問題"><span>分析問題</span></a></h2><p>解決這問題的關鍵在於,瀏覽器在滾動時,到底滾動到了誰?</p><h4 id="element-怎麼滾動" tabindex="-1"><a class="header-anchor" href="#element-怎麼滾動"><span>Element 怎麼滾動?</span></a></h4><p>上面提到,<code>#app</code> 滾動還是垂直方向的原因是:我們將 html 設置為 <code>overflow: hidden</code>,此時滾動事件實際是傳遞到 <code>#app</code>,滾動方向就還是根據畫面方向而是直的,這是因為事件傳遞時並不知道我們的 <code>#app</code>已經打橫。</p><h4 id="預設是-html-滾動-還是-window-滾動" tabindex="-1"><a class="header-anchor" href="#預設是-html-滾動-還是-window-滾動"><span>預設是 html 滾動?還是 window 滾動?</span></a></h4><p>同樣適用於整份文檔的最外層元素 html,而整個視窗 window 同樣也是一個元素,他的寬高就是我們的螢幕大小,也因此在不設定任何東西狀態下,當 html 元素大於視窗大小時,我們能夠對 window 進行滾動。</p><p>上面我們的 <code>transform-origin</code> 是 <code>50vmin</code> 雖然視覺上是吻合的,但實際這種轉法會讓瀏覽器無法正確判斷元素的長寬,從而導致滾動事件的異常。</p><h4 id="分析結論" tabindex="-1"><a class="header-anchor" href="#分析結論"><span>分析結論</span></a></h4><p>到這邊,我們已經知道了。</p><ol><li><p>當我們透過 CSS 將 html 元素旋轉 90 度時,其實最外層 window 還是直的,當然滾動的方向仍然是以 window 的方向為主,也就會發生上下滑動畫面,html 元素卻左右滑動的奇特狀況(XD,第一次看到這問題時快笑死)</p></li><li><p><code>transform-origin</code> 必須以完整方式轉向,不能從中心轉。</p></li></ol><h2 id="解決辦法" tabindex="-1"><a class="header-anchor" href="#解決辦法"><span>解決辦法</span></a></h2><p>綜合上面分析得出結論,我們必須將瀏覽器的滾動事件傳到對的人身上,我們這邊就不討論 js 的解法了,以純 CSS 進行處理可以更節省更多效能。</p><h4 id="step-1-將-window-下-html-條件鎖住" tabindex="-1"><a class="header-anchor" href="#step-1-將-window-下-html-條件鎖住"><span>Step 1. 將 window 下 html 條件鎖住</span></a></h4><p>首先將 html 的寬設為螢幕寬如下,並且根據畫面比例 <code>orientation</code> 來設置 <code>overflow: hidden</code>,滾動事件也就不會對應觸發在他身上,透過這個方式我們將滾動事件穿透到了 body 上,另外 <code>transform-origin</code> 是以左上為圓心完整的打橫,也就可以順利將滾動事件觸發。</p><div class="language-scss line-numbers-mode" data-highlighter="prismjs" data-ext="scss"><pre><code class="language-scss"><span class="line"><span class="token selector">html </span><span class="token punctuation">{</span></span>
29<span class="line">  <span class="token property">width</span><span class="token punctuation">:</span> 100vmax<span class="token punctuation">;</span></span>
30<span class="line">  <span class="token atrule"><span class="token rule">@media</span> only screen <span class="token operator">and</span> <span class="token punctuation">(</span><span class="token property">orientation</span><span class="token punctuation">:</span> landscape<span class="token punctuation">)</span></span> <span class="token punctuation">{</span></span>
31<span class="line">    <span class="token property">overflow-x</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span></span>
32<span class="line">  <span class="token punctuation">}</span></span>
33<span class="line">  <span class="token atrule"><span class="token rule">@media</span> only screen <span class="token operator">and</span> <span class="token punctuation">(</span><span class="token property">orientation</span><span class="token punctuation">:</span> portrait<span class="token punctuation">)</span></span> <span class="token punctuation">{</span></span>
34<span class="line">    <span class="token property">overflow-y</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span></span>
35<span class="line">    <span class="token comment">// 轉向後移動到對的位置</span></span>
36<span class="line">    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">rotate</span><span class="token punctuation">(</span>90deg<span class="token punctuation">)</span> <span class="token function">translateY</span><span class="token punctuation">(</span>-100%<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
37<span class="line">    <span class="token property">transform-origin</span><span class="token punctuation">:</span> top left<span class="token punctuation">;</span></span>
38<span class="line">  <span class="token punctuation">}</span></span>
39<span class="line">  <span class="token selector">body </span><span class="token punctuation">{</span></span>
40<span class="line">    <span class="token comment">// 這裡可以不用設寬高</span></span>
41<span class="line">    <span class="token property">margin</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span></span>
42<span class="line">  <span class="token punctuation">}</span></span>
43<span class="line"><span class="token punctuation">}</span></span>
44<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="step-2-將-app-維持預設狀態" tabindex="-1"><a class="header-anchor" href="#step-2-將-app-維持預設狀態"><span>Step 2. 將 #app 維持預設狀態</span></a></h4><div class="language-scss line-numbers-mode" data-highlighter="prismjs" data-ext="scss"><pre><code class="language-scss"><span class="line"><span class="token comment">// 移除 #app 相關寬高設定,維持自然預設</span></span>
45<span class="line"><span class="token selector">#app </span><span class="token punctuation">{</span></span>
46<span class="line">  <span class="token selector">.box </span><span class="token punctuation">{</span></span>
47<span class="line">    <span class="token property">height</span><span class="token punctuation">:</span>
47 1000px<span class="token punctuation">;</span></span>
48<span class="line">    <span class="token property">background</span><span class="token punctuation">:</span> lightblue<span class="token punctuation">;</span></span>
49<span class="line">  <span class="token punctuation">}</span></span>
50<span class="line"><span class="token punctuation">}</span></span>
51<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="結論" tabindex="-1"><a class="header-anchor" href="#結論"><span>結論</span></a></h2><p>透過這個問題,又加深了一次整個瀏覽器文檔的理解跟體會,CSS Model Box 概念跟滾動功能息息相關啊~~</p><p>以上就是小弟本人親身開發的一些體會,其實本來這問題牽涉到更多東西,例如滾動套件的滾動對象、以及要鎖屏滾動的同時,又要在整個頁面中插入背景圖等等,真的非常混亂,這次的文章主要是將最核心的問題抽離開來講解的,希望各位能夠在遇到時不會慌了手腳哈哈。</p><p>本篇純屬個人理解,寫得不好或是不周之處,還請各位大大們不吝賜教拉~^_^</p>`,29)),p(e,{hashtags:"css,overflow,landscape"})])}const k=t(u,[["render",d]]),v=JSON.parse('{"path":"/articles/css/landscape-fix-scroll.html","title":"CSS 畫面鎖橫屏時,滾動的問題!!","lang":"zh-TW","frontmatter":{},"git":{"updatedTime":1748788505000,"contributors":[{"name":"Johnny Wang","username":"","email":"[email protected]","commits":2},{"name":"johnnywang1994","username":"johnnywang1994","email":"[email protected]","commits":2,"url":"https://github.com/johnnywang1994"},{"name":"Lindy Liao","username":"","email":"[email protected]","commits":1}],"changelog":[{"hash":"f01bfa128b4d33fbeddb8abb1697b5391b273d28","time":1748788505000,"email":"[email protected]","author":"Lindy Liao","message":"UPD"},{"hash":"71ccb7693345c8ddc2f554e00f8a0ce73af2b783","time":1648521821000,"email":"[email protected]","author":"johnnywang1994","message":"UPD: upgrade to v2"},{"hash":"da1521dcf805739a83e5efa4e52581013a51dcad","time":1638541816000,"email":"[email protected]","author":"johnnywang1994","message":"UPD: update sociallinks"},{"hash":"e4934b227e750cf780d547efbbb68d62ffe4580d","time":1629951525000,"email":"[email protected]","author":"Johnny Wang","message":"UPD: update"},{"hash":"51e618d93d4f837fbce25a1e1f0a9783cbc46b6a","time":1624012650000,"email":"[email protected]","author":"Johnny Wang","message":"INIT"}]},"filePathRelative":"articles/css/landscape-fix-scroll.md"}');export{k as comp,v as data};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.