* 仕様書

[REFS[
- [53] [CITE@en[Visual formatting model]], [TIME[2020-03-17 13:15:41 +09:00]] <https://drafts.csswg.org/css2/visuren.html#viewport>
]REFS]

* 意味

[3] [[連続媒体]]の[[利用者エージェント]]は、通常[[利用者]]に対して [DFN@en[[[viewport]]]]
を提供します。[[利用者]]は [[viewport]] を通じて[[文書]]にアクセスできます。
[[Viewport]] は[[窓]]その他の[RUBYB[[[画面]]]@en[screen]]上の[RUBYB[表示領域]@en[viewing area]]です。
[SRC@en[[[CSS 2.1]] 9.1.1]]

[55] 
通常の [[GUI]] システム上の[[視覚的ブラウザー]]では、
[[Webページ]]を表示する[[窓]] (の[[タブ]])
のうち、
[[タイトルバー]]、[[メニューバー]]、[[ツールバー]]、[[アドレスバー]]、[[ステータスバー]]、
[[タブ]]、[[窓]]の枠線のような [[UI]] 要素を除外した、
[[Webページ]]自体の表示領域を指します。

[56] 
[[Webページ]]全体を[[スクロール]]するための[[スクロールバー]]は、
[[viewport]] に含まれます。

[57] 
表示領域に重なって一時的に表示されたり隠れたりする[[ステータスバー]]や、
[[スクロール]]状態によって表示されたりされなかったりする[[アドレスバー]]の類は、
[[viewport]] には含まれませんが、 [[viewport]] の大きさの決定はそれらが表示されない状態によります
[SRC[>>58]]。


* 状態

[49] 
[FIG(list members)[
: [F[幅]] :
: [F[高さ]] :
: [F[scrolling box]] :
: [F[scrolling area]] :
]FIG]

* 大きさ

[54] 
[[viewport]]
は[F[幅]]と[F[高さ]]の[[寸法]]を持ちます。

[63] 
多くの [[Webブラウザー]]では、
[[寸法]]が動的に変化し得ます。
[[寸法]]の他、可視状態なども変化し得ます。
[SEE[ [[窓 (Web)]] ]]


[4]
[[利用者エージェント]]は [[viewport]] の大きさが変更された時に[[文書]]の[[配置]]を変更して[['''構いません''']]。
[SRC@en[[[CSS 2.1]] 9.1.1.]]

[60] 
[[viewport]] のサイズが変化すると、
それによって定義されている[[初期包含ブロック]]のサイズも変化します。

[59] 
[[viewport]] のサイズに連動する単位として [CODE[vh]], [CODE[vw]]
などがあります。厳密には[[初期包含ブロック]]のサイズによって決められます。

[65] 
[[媒体クエリー]]の[[媒体機能]] [CODE[width]], [CODE[height]]
は
[[viewport]] の[F[幅]]と[F[高さ]]となっています。
[CODE[aspect-ratio]] と [CODE[orientation]]
もこれに関係して定義されています。

[64] [[DOM]]
では
[CODE[window.innerWidth]],
[CODE[window.innerHeight]]
でアクセスできます。

* 画布との関係

[5]
[[Viewport]] が[[画布]]中の[[文書]]が[[レンダリング]]されている[RUBYB[[[領域]]]@en[area]]より小さい時、
[[利用者エージェント]]は[[スクロール機構]]を提供する[['''べきです''']]。
[SRC@en[[[CSS 2.1]] 9.1.1]]

[6]
[[画布]]1つに対して [[viewport]] は高々1つです。
[SRC@en[[[CSS 2.1]] 9.1.1]]

** 包含ブロックとしての viewport

[9] [[連続媒体]]では、[[根要素]]の基準となる[[包含ブロック]]は [[viewport]]
の[[次元]]を持つ[[矩形]]です。これを[DFN[[[初期包含ブロック]]]]と呼びます。
[[画布]]の[[原点]]がその[[原点]]となります。
[SRC@en[[[CSS 2.1]] 10.1]]

*** 固定配置

[8]
[CODE(CSS)@en[[[position]]: [[fixed]]]] ([[固定配置]]) の[[箱]]については、
[[包含ブロック]]が [[viewport]] により[[確立]]されます。
[SRC@en[[[CSS 2.1]] 9.6.1, 10.1]]

[7]
[CODE(CSS)@en[[[position]]: [[fixed]]]] ([[固定配置]])
の[[箱]]は、
-[[媒体型]]が [CODE(CSS)@en[[[handheld]]]]、[CODE(CSS)@en[[[projection]]]]、
[CODE(CSS)@en[[[screen]]]]、[CODE(CSS)@en[[[tty]]]]、
[CODE(CSS)@en[[[tv]]]] の場合、 [[viewport]] に対して固定され、[[スクロール]]によって移動しません。
-[[媒体型]]が [CODE(CSS)@en[[[print]]]] の場合、[[頁]]が [[viewport]]
を通じて見られる場合 (例えば[[印刷プレビュー]]の時) であっても [[viewport]]
ではなく[[頁箱]]に対して固定されます。

[SRC@en[[[CSS 2.1]] 9.3.1]]

[10] 
[[固定配置要素]]に関する[[静的位置]]の算出においては、
[[固定配置要素]]の[[包含ブロック]]は [[viewport]]
ではなく[[初期包含ブロック]]であるものとみなします。
[SRC@en[[[CSS 2.1]] 10.3.7, 10.6.4]]

;; [[初期包含ブロック]]は常に[[画布]]の[[原点]]に錨付けされていますが、
[[viewport]] の[[画布]]に対する位置は変化します。

** 背景

[12] [CODE(CSS)@en[[[background-attachment]]: [[fixed]]]] は[[背景画像]]を
[[viewport]] に対して固定します
[SRC@en[[[CSS 2.1]] 14.2.1]]。

[13] >>12 の場合、 [CODE(CSS)@en[[[background-attachment]]]] は [[viewport]]
を基準に解釈されます [SRC@en[[[CSS 2.1]] 14.2.1]]。

** スクロール

[11] [[HTML文書]]で [CODE(HTMLe)@en[[[html]]]] [[要素]]の [CODE(CSS)@en[[[overflow]]]]
[[算出値]]が [CODE(CSS)@en[[[visible]]]] の場合、 [CODE(HTMLe)@en[[[body]]]]
[[要素]]の [CODE(CSS)@en[[[overflow]]]] [[算出値]]が [[viewport]] に適用されます。
それ以外の場合、[[根要素]]の [CODE(CSS)@en[[[overflow]]]] が [[viewport]]
に適用されます。 [[Viewport]] に適用された[[要素]]の [CODE(CSS)@en[[[overflow]]]]
の[[使用値]]は [CODE(CSS)@en[[[visible]]]] になります。
[[Viewport]] の [CODE(CSS)@en[[[overflow]]]] が [CODE(CSS)@en[[[visible]]]]
の場合、 [CODE(CSS)@en[[[auto]]]] と解釈されます。
[SRC@en[[[CSS 2.1]] 11.1.1]]

[26] [[スクロール・バー]]が現れる時の [[viewport]]、あるいは[[初期包含ブロック]]に[[スクロール・バー]]の領域が含まれるのかどうかは不明です。
普通の[[箱]]の場合を類推すると [[viewport]] の[[内容辺]]相当 = [[詰め辺]]相当の外側で、
[[初期包含ブロック]]に含まれないと解釈するのが妥当だと思いますが・・・。

[62] 厳密な[[規定]]がどこにあるか不明ですが、
[CITE@en[CSS Values and Units Module Level 4]], [TIME[2020-05-01 10:43:32 +09:00]] <https://drafts.csswg.org/css-values/#viewport-relative-lengths>
にも[[スクロールバー]]は [[viewport]] に含まれ [[ICB]]
には含まれないと注記されています。
[CITE@en[CSSOM View Module]], [TIME[2020-05-01 10:44:00 +09:00]] <https://drafts.csswg.org/cssom-view/#dom-window-innerwidth>
と
[CITE@en[Media Queries Level 4]], [TIME[2020-05-01 14:43:54 +09:00]] <https://drafts.csswg.org/mediaqueries-4/#mf-dimensions>
には [[viewport]] に[[スクロールバー]]が含まれると明記されています。
(わざわざ明記が必要なのは、単一の厳密な規定を欠くためとも思われます。)

** 内容辺、境界辺

[14] 本来 [[CSS]] の [[viewport]] は1つの[[矩形]]ですが、
便宜上[[箱]]同様に[DFN[[RUBYB[[[内容辺]]]@en[content edge]]]]/[DFN[[RUBYB[内容箱]@en[content box]]]]、
[DFN[[RUBYB[[[境界辺]]]@en[border edge]]]]/[DFN[[RUBYB[境界箱]@en[border box]]]]という用語を使います。

[15] 通常 [[CSS]] によって何らかの形でアクセス可能なのは[[内容箱]]・[[スクロール・バー]]とその内側だけです。
その外側の[[境界線]]は、あったとしても [[Webブラウザ]]の[[利用者界面]]に属するものです。

[16] [[WinIE]] の[[奇癖モード]]では、 [CODE(HTMLe)@en[[[body]]]] [[要素]]の
[CODE(CSS)@en[[[border]]]] が [[viewport]] の[[境界領域]]になります。
[CODE(CSS)@en[[[border]]]] を指定しない場合や[[標準モード]]では既定の境界が[[レンダリング]]され、
[[CSSOM]] [CODE(DOMa)@en[[[offset[VAR[*]]]]]] などに影響します。

** 単位

[61] 
[[初期包含ブロック]]の[[寸法]]によって定まる[[単位][CSSの単位]]に、
[CODE[vh]],
[CODE[vw]],
[CODE[vmin]],
[CODE[vmax]],
[CODE[vi]],
[CODE[vb]]
があります。

** CSSOM による大きさの取得

*** 内容箱

**** Firefox

[17] 
- [[無奇癖モード]]
-- [CODE(JS)@en[[[document]].[[documentElement]].[[client*]]]]
- [[奇癖モード]]
-- [CODE(JS)@en[[[document]].[[body]].[[client*]]]]
--- ただし、 [CODE(HTMLe)@en[[[html]]]], [CODE(HTMLe)@en[[[body]]]] の両方が
[CODE(CSS)@en[[[overflow]]]] による[[スクロール・バー]]を持つ場合を除きます。

**** Safari

[18]
- [[無奇癖モード]]
-- [CODE(JS)@en[[[document]].[[documentElement]].[[client*]]]]
- [[奇癖モード]]
-- [CODE(JS)@en[[[document]].[[body]].[[client*]]]]
([CODE(DOMa)@en[[[clientTop]]]]、[CODE(DOMa)@en[[[clientLeft]]]] に
[CODE(HTMLe)@en[[[body]]]] の [CODE(CSS)@en[[[border-top-width]]]]、
[CODE(CSS)@en[[[border-left-width]]]] が入ります。)

**** Opera

[20]
- [[無奇癖モード]]
-- [CODE(JS)@en[[[document]].[[documentElement]].[[client*]]]]
- [[奇癖モード]]
-- [CODE(JS)@en[[[document]].[[body]].[[client*]]]]
-- [CODE(JS)@en[[[document]].[[documentElement]].[[client*]]]] (横方向のみ)

**** WinIE

[22]
- [[無奇癖モード]]
-- [CODE(JS)@en[[[document]].[[documentElement]].[[offset*]]]]
-- [CODE(JS)@en[[[document]].[[documentElement]].[[client*]]]] ([[境界辺]]が[[原点]])
- [[奇癖モード]]
-- [CODE(JS)@en[[[document]].[[body]].[[client*]]]]

*** 内容箱 + スクロール・バー

**** Firefox

[24] 
- [CODE(JS)@en[[[window.innerWidth]]]], [CODE(JS)@en[[[document.innerHeight]]]]

**** Safari

[25] 
- [CODE(JS)@en[[[window.innerWidth]]]], [CODE(JS)@en[[[document.innerHeight]]]]

**** Opera

[19]
- [[奇癖モード]]
-- [CODE(JS)@en[[[document]].[[body]].[[offset*]]]]
- [CODE(JS)@en[[[window.innerWidth]]]], [CODE(JS)@en[[[document.innerHeight]]]]

*** 境界箱

**** WinIE

[21] 
-[[奇癖モード]]
-- [CODE(JS)@en[[[document]].[[documentElement]].[[offset*]]]]
-- [CODE(JS)@en[[[document]].[[body]].[[offset*]]]]
-- [CODE(JS)@en[[[document]].[[documentElement]].[[scroll*]]]]
- [CODE(JS)@en[[[document]].[[documentElement]].[[getBoundingClientRect]]()]]

*** Viewport と初期包含ブロックのずれ

[23] 
- 原則として
-- [[無奇癖モード]]: [CODE(JS)@en[[[document]].[[documentElement]].[[scroll*]]]]
-- [[奇癖モード]]: [CODE(JS)@en[[[document]].[[body]].[[scroll*]]]]
--- ただし、[[Firefox]] で [CODE(HTMLe)@en[[[html]]]], [CODE(HTMLe)@en[[[body]]]] の両方が
[CODE(CSS)@en[[[overflow]]]] による[[スクロール・バー]]を持つ場合を除きます。
- [[Safari]] では常に: [CODE(JS)@en[[[document]].[[body]].[[scroll*]]]]
- [CODE(JS)@en[[[window.pageXOffset]]]], [CODE(JS)@en[[[window.pageYOffset]]]] ([[WinIE]] 以外)
- [CODE(JS)@en[[[window.scrollX]]]], [CODE(JS)@en[[[window.scrollY]]]] ([[WinIE]], [[Opera]] 以外)

* [CODE(HTML)@en[<meta name=viewport>]]

[EG[
[45] 多くの場合、次のようにするのが適切です。
[PRE(HTML code)[
<[[meta]] [[name]]="[[viewport]]" [[content]]="[[width]]=[[device-width]],[[initial-scale]]=1">
]PRE]
]EG]

* 歴史


[2] 
-[[CSS 2.1]]
--[CSECTION@en[9.1.1 The viewport]]
<http://www.w3.org/TR/2007/CR-CSS21-20070719/visuren.html#viewport>
--[CSECTION@en[10.1 Definition of "containing block"]]
<http://www.w3.org/TR/2007/CR-CSS21-20070719/visudet.html#containing-block-details>
--[CSECTION@en[11.1.1 Overflow: the [CODE(CSS)@en['overflow']] property]]
<http://www.w3.org/TR/2007/CR-CSS21-20070719/visufx.html#overflow>
--[CSECTION@en[14.2.1 Background properties: [CODE(CSS)['background-color']], [CODE(CSS)['background-image']], [CODE(CSS)['background-repeat']], [CODE(CSS)['background-attachment']], [CODE(CSS)['background-position']], and [CODE(CSS)['background']]]]
<http://www.w3.org/TR/2007/CR-CSS21-20070719/colors.html#background-properties>



[1]
[CITE[Mapion touch - A blog? with Σαιτω]] ([TIME[2008-02-09 23:15:11 +09:00]] 版) <http://d.hatena.ne.jp/saiton/20071112/1194870931>

[27] [CITE@ja[ニンテンドーDSiブラウザー:Q&A]] ([TIME[2008-12-16 10:58:36 +09:00]] 版) <http://www.nintendo.co.jp/ds/dsiware/hngj/q_and_a.html>

>
Q.19
>	ニンテンドーDSiブラウザーでうまく表示できるホームページを作りたいのですが・・・
>
A.19
>	<meta name="viewport" content="width=240" /> を HTML の <head>...</head> 内に指定することで、幅240px高さ352pxで、横スクロール縮小表示無く、2画面が縦につながった状態でHTMLを表示させることができます。
>
ページレイアウトをpx(ピクセル)単位ではなくて、%(パーセンテージ)を基準として行われている場合は、<meta name="viewport" content="width=device-width" /> を指定してください。

[28] [CITE@ja[Travellers Tales : iPod touch/iPhone の viewport 属性の区切りはセミコロンではなくカンマ]] ([TIME[2009-01-19 15:29:59 +09:00]] 版) <http://travel-lab.info/tech/pblog/article.php?id=154>

[29] [CITE[IRC logs: freenode / #whatwg / 20090915]]
([TIME[2009-10-31 11:41:27 +09:00]] 版)
<http://krijnhoetmer.nl/irc-logs/whatwg/20090915#l-322>

[30] [CITE@en[Safari Dev Center: Safari HTML Reference: Supported Meta Tags]]
([TIME[2009-12-09 23:16:02 +09:00]] 版)
<http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html>

[31] [CITE@en-us[Developing Web Applications for Internet Explorer Mobile 6 on Windows Mobile 6.5]]
([TIME[2010-06-09 17:30:37 +09:00]] 版)
<http://msdn.microsoft.com/en-us/library/dd938878.aspx>

[32] [CITE@en[CSS Device Adaptation]]
( ([TIME[2010-11-03 06:00:41 +09:00]] 版))
<http://dev.w3.org/csswg/css-device-adapt/>

[33] [[Android]] のブラウザは
[PRE(JS example code)[
var div = document.createElement ('div');
div.innerHTML = '<meta name=viewport content="width=device-width">';
]PRE]
... のようなコードを実行するだけでなぜかページの一番上にスクロールされます。

[34] [CITE[Introduction – SVG 1.1 (Second Edition)]]
( ([TIME[2011-08-10 12:35:27 +09:00]] 版))
<http://www.w3.org/TR/2011/REC-SVG11-20110816/intro.html#TermViewport>

[35] [CITE@en[CSS Device Adaptation]]
( ([TIME[2011-09-15 02:28:23 +09:00]] 版))
<http://www.w3.org/TR/2011/WD-css-device-adapt-20110915/>

[36] [CITE[IRC logs: freenode / #whatwg / 20120315]]
( ([TIME[2012-03-21 08:57:20 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20120315#l-469>

[37] [CITE[Targeting Screens from Web Apps | Android Developers]]
( ([TIME[2012-07-07 16:39:23 +09:00]] 版))
<http://developer.android.com/guide/webapps/targeting.html>

[38] [CITE[Bug 101217 – Remove support for "desktop-width" in the viewport meta tag]]
( ([TIME[2012-11-18 06:38:51 +09:00]] 版))
<https://bugs.webkit.org/show_bug.cgi?id=101217>

[39] [CITE@en[Re: Addressing space outside a document's root element]]
( ([[Boris Zbarsky]] 著, [TIME[2013-05-13 23:01:45 +09:00]] 版))
<http://lists.w3.org/Archives/Public/www-style/2013May/0303.html>

[40] [CITE[Widget Interface]]
( ([TIME[2013-10-29 00:58:56 +09:00]] 版))
<http://www.w3.org/TR/widgets-apis/#viewport>

[41] [CITE@ja[これがスマートフォン向けサイトを作るときの viewport 設定3パターンだ - てっく煮ブログ]]
([TIME[2014-09-16 00:48:23 +09:00]] 版)
<http://tech.nitoyon.com/ja/blog/2013/02/15/viewport/>

[FIG(quote)[
[FIGCAPTION[
[42] [CITE@en[Safari 7.1]]
([TIME[2015-11-04 23:12:55 +09:00]] 版)
<https://developer.apple.com/library/safari/releasenotes/General/WhatsNewInSafari/Articles/Safari_7_1.html#//apple_ref/doc/uid/TP40014305-CH6-SW2>
]FIGCAPTION]

> A new property, minimal-ui, has been added for the "viewport" metatag in iOS to allow minimizing the top and bottom bars as a page loads on iPhone. For example:
> <meta name="viewport" content="width=1024, minimal-ui">
> Tapping the top bar brings the bars back; tapping back in the content dismisses them again.

]FIG]


[FIG(quote)[
[FIGCAPTION[
[43] [CITE@en[Safari 9.0]]
([TIME[2015-11-04 23:18:05 +09:00]] 版)
<https://developer.apple.com/library/safari/releasenotes/General/WhatsNewInSafari/Articles/Safari_9.html#//apple_ref/doc/uid/TP40014305-CH9-SW36>
]FIGCAPTION]

> Viewport meta tags using "width = content-width" cause the page to scale down to fit content that overflows the viewport bounds. You can override this behavior by adding "shrink-to-fit = no" to your meta tag as shown below. The added value will prevent the page from scaling to fit the viewport.
> <meta name = "viewport" content = "width = content-width, initial-scale = 1.0, shrink-to-fit = no“>

]FIG]


[44] [CITE@en[Gloss the term "viewport" · whatwg/html@d530547]]
([TIME[2016-02-27 11:43:59 +09:00]] 版)
<https://github.com/whatwg/html/commit/d53054738717895fe534a4e1a1e5e3600be695ac>

[FIG(quote)[
[FIGCAPTION[
[46] ([TIME[2016-04-18 15:10:24 +09:00]] 版)
<http://taart-design.com/>
]FIGCAPTION]

> 
>     <meta name="viewport" content="target-densitydpi=device-dpi, width=1030, maximum-scale=1.5, user-scalable=yes">
>     <!--<meta name="viewport" content="width=device-width,initial-scale=1.0" />-->

]FIG]


[FIG(quote)[
[FIGCAPTION[
[47] [CITE[365LIFE 不動産・賃貸セレクトショップ静岡県浜松]]
( ([TIME[2016-05-16 14:02:21 +09:00]]))
<http://365life-realestate.com/>
]FIGCAPTION]

> 
> <!--jsでviewportを切り替えるタブレットは1010pxでPC表示、スマホは端末に合わせて表示-->
> <script type="text/javascript">
> if ((navigator.userAgent.indexOf('iPhone') > 0) || navigator.userAgent.indexOf('iPod') > 0 || navigator.userAgent.indexOf('Android') > 0) {
> 	    document.write('<meta name="viewport" content="initial-scale=1.0">');
> 	}else{
> 	    document.write('<meta name="viewport" content="width=1010">');
> 	}
> </script>

]FIG]


[FIG(quote)[
[FIGCAPTION[
[48] [CITE@en-US[UC mobile phone browser (U3 kernel) related documentation]]
( ([TIME[2016-06-01 19:23:42 +09:00]]))
<http://www.programering.com/a/MDNxAjMwATU.html>
]FIGCAPTION]

> Description: after the opening, when the scaling operation, only magnified images and text and other elements on the page, but not enlarged screen width, thus avoiding the or so the scroll bar.
> Parameters:
> uc-fitscreen=no: Do not open the '''['''default''']'''
> uc-fitscreen=yes: Open
> Usage:
> 1 <!--  Open UC to fit the screen layout  -->
> 2 <meta name="viewport" content="uc-fitscreen=yes"/>
> Versioning support: 8.5 patch +

]FIG]


[50] [CITE@en[Re: '''['''css-device-adapt''']''' add warning to user-scalable=no / user-zoom / etc  relating to accessibility/usability?]]
([[Florian Rivoal]]著, [TIME[2016-09-30 15:22:22 +09:00]])
<https://lists.w3.org/Archives/Public/www-style/2016Sep/0130.html>

[FIG(quote)[
[FIGCAPTION[
[51] [CITE@en[Mobile Web Application Best Practices]]
([TIME[2017-10-02 19:40:59 +09:00]])
<https://www.w3.org/TR/mwabp/#bp-viewport>
]FIGCAPTION]

> the term "JavaScript" is used in place of the (arguably more correct) term "ECMAScript" in order to provide consistency with the companion Web application technologies (JSON and AJAX) which are in common use and both implicitly refer to JavaScript in their names.

]FIG]



[52] [[JavaScript]] で勝手に内容が差し替わって、前のページに戻ったりしても元と同じ内容にならないことが多いので
(ヘッドラインとか[[広告]]とかその他の[[アニメーション]]効果とか)、
[[viewport]] を常に[[録画]]しておいて一定期間内なら自由に[[巻き戻し]]て[[再生]]できたら便利そう。
[TIME[2018-04-17T04:17:59.700Z]]


[58] [CITE@en[URL Bar Resizing  |  Web  |  Google Developers]]
([TIME[2019-01-15 04:34:15 +09:00]])
<https://developers.google.com/web/updates/2016/12/url-bar-resizing>


[66] [CITE@en[Editorial: nested browsing context is a member, not a type]]
([[annevk]], [TIME[2019-11-27 02:46:03 +09:00]], [TIME[2022-01-18T10:07:30.000Z]])
<https://github.com/whatwg/html/commit/6b737bbc428facf34ec3728c0912cf9e172d0ea4>