<?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/"
	>

<channel>
	<title>swiftui scrollview scroll to position &#8211; swiftyplace</title>
	<atom:link href="http://www.swiftyplace.com/blog/tag/swiftui-scrollview-scroll-to-position/feed" rel="self" type="application/rss+xml" />
	<link>http://www.swiftyplace.com</link>
	<description>Learn how to build amazing apps with SwiftUI and Combine</description>
	<lastBuildDate>Tue, 28 Nov 2023 15:43:39 +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>http://www.swiftyplace.com/wp-content/uploads/2023/08/cropped-logo-1-32x32.png</url>
	<title>swiftui scrollview scroll to position &#8211; swiftyplace</title>
	<link>http://www.swiftyplace.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>How to use SwiftUI ScrollView to Create Amazing Collection Views</title>
		<link>http://www.swiftyplace.com/blog/how-to-use-swiftui-scrollview?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-use-swiftui-scrollview</link>
					<comments>http://www.swiftyplace.com/blog/how-to-use-swiftui-scrollview#comments</comments>
		
		<dc:creator><![CDATA[Karin Prater]]></dc:creator>
		<pubDate>Thu, 02 Feb 2023 08:27:25 +0000</pubDate>
				<category><![CDATA[SwiftUI]]></category>
		<category><![CDATA[SwiftUI Components]]></category>
		<category><![CDATA[scrollview SwiftUI]]></category>
		<category><![CDATA[SwiftUI scrollview]]></category>
		<category><![CDATA[swiftui scrollview list]]></category>
		<category><![CDATA[swiftui scrollview offset]]></category>
		<category><![CDATA[swiftui scrollview scroll to position]]></category>
		<guid isPermaLink="false">https://swiftyplace.com/?p=1064</guid>

					<description><![CDATA[<p> Learn how to use SwiftUI ScrollView, a scrollable container view in SwiftUI. Explore its features that allow you to scroll horizontally or vertically</p>
<p>The post <a rel="nofollow" href="http://www.swiftyplace.com/blog/how-to-use-swiftui-scrollview">How to use SwiftUI ScrollView to Create Amazing Collection Views</a> appeared first on <a rel="nofollow" href="http://www.swiftyplace.com">swiftyplace</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">In this blog post, I will show you how to use SwiftUI ScrollView, including vertical and horizontal scrolling, how to programmatically scroll, and how to create very complex layout views. </p>



<p class="wp-block-paragraph">ScrollView got a lot of new updates with iOS 17 and macOS 14. These include paging behaviour, containerRelativeFrame, custom scroll bounce behaviour, and reading the scroll position. You can also add scroll animations with scrollTransition and visualEffect.</p>



<p class="wp-block-paragraph">I will show you a lot of different examples and use cases. So that by the end of this blog, you will want to start using ScrollView in your next iOS project and build amazing-looking UI.</p>



<p class="wp-block-paragraph"><strong>Download the project files from <a href="https://school.swiftyplace.com/17130/files/63e2928f370fa_1675793039_scrollviewproject.zip" target="_blank" rel="noopener">here </a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b07.png" alt="⬇" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong></p>



<div style="height:26px" aria-hidden="true" class="wp-block-spacer"></div>



			
			
										
			
			


<div style="height:58px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">What is a ScrollView</h2>



<p class="wp-block-paragraph">The scroll view is a scrollable component in SwiftUI. It is a container view that shows its content either in a horizontal or vertical scroll direction. It does not allow to zoom in or out of its content.</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">What is the difference between ScrollView and List in SwiftUI?</h2>



<p class="wp-block-paragraph">SwiftUI provides developers with two ways to create scrollable content: <a href="https://www.swiftyplace.com/blog/swiftui-list-view-a-deep-dive-into-one-of-the-most-important-components-of-swiftui" data-type="link" data-id="https://www.swiftyplace.com/blog/swiftui-list-view-a-deep-dive-into-one-of-the-most-important-components-of-swiftui">List</a> and ScrollView. ScrollView is the more versatile option both in terms of custom styling as well as adjusting scroll behavior. For example, ScrollView allows for programmatical scrolling, set a horizontal scroll view, show grid views and create sections with different scroll axis similar to UICollectionView in UIKit. </p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph"><strong>Showing Large Data Sets</strong></p>



<p class="wp-block-paragraph">The List view is more efficient when it comes to memory usage due to its ability to lazy load only what is necessary as you scroll, while a ScrollView loads all content at once into memory. When working with large data sets inside a ScrollView, make use of LazyVStack and LazyHStack. These load their data lazily similar to List.</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph"><strong>Options for Custom Styling</strong></p>



<p class="wp-block-paragraph">When it comes to customizing the styling, ScrollView is more versatile while List gives you a good default appearance right out of the box, which is adjusted for the different Apple platforms. If you are looking to make a cross-platform app, you can take advantage of List to quickly create a great-looking UI.</p>



<div style="height:32px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">How to add content to SwiftUI ScrollView?</h2>



<p class="wp-block-paragraph">To add content to ScrollView, you can embed your SwiftUI views in a ScrollView. Per default, it will show the subviews like a vertical stack. A typical use case is if you want to fit your content on the iPhone screen, especially for smaller screen sizes or for larger dynamic types. In the following example, I embed the view in a ScrollView, which makes it easily adaptable for most situations:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="struct ContentView: View {
    let description = &quot;Lorem ipsum ...&quot;

    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 20) {
                Image(&quot;minime&quot;)
                    .resizable()
                    .scaledToFill()
                    .frame(width: 350, height: 350)
                    .clipped()

                Text(&quot;Mini-me&quot;)
                    .font(.largeTitle)

                Text(description)
                    .multilineTextAlignment(.leading)
            }
            .padding()
        }
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">struct</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ContentView</span><span style="color: #F6F6F4">: View {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> description </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">Lorem ipsum ...</span><span style="color: #DEE492">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> body: </span><span style="color: #F286C4">some</span><span style="color: #F6F6F4"> View {</span></span>
<span class="line"><span style="color: #F6F6F4">        ScrollView {</span></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #97E1F1">VStack</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">alignment</span><span style="color: #F6F6F4">: .leading, </span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">20</span><span style="color: #F6F6F4">) {</span></span>
<span class="line"><span style="color: #F6F6F4">                </span><span style="color: #97E1F1">Image</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">minime</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">                    .</span><span style="color: #97E1F1">resizable</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">                    .</span><span style="color: #97E1F1">scaledToFill</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">                    .</span><span style="color: #97E1F1">frame</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">width</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">350</span><span style="color: #F6F6F4">, </span><span style="color: #97E1F1">height</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">350</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">                    .</span><span style="color: #97E1F1">clipped</span><span style="color: #F6F6F4">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">                </span><span style="color: #97E1F1">Text</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">Mini-me</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">                    .</span><span style="color: #97E1F1">font</span><span style="color: #F6F6F4">(.largeTitle)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">                </span><span style="color: #97E1F1">Text</span><span style="color: #F6F6F4">(description)</span></span>
<span class="line"><span style="color: #F6F6F4">                    .</span><span style="color: #97E1F1">multilineTextAlignment</span><span style="color: #F6F6F4">(.leading)</span></span>
<span class="line"><span style="color: #F6F6F4">            }</span></span>
<span class="line"><span style="color: #F6F6F4">            .</span><span style="color: #97E1F1">padding</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">        }</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<div style="height:26px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-image"><img decoding="async" src="https://www.swiftyplace.com/wp-content/uploads/2023/08/scrollview_fit_content-1024x738.webp" alt="SwiftUI ScrollView used for fiting the content on smaller iphone screens or larger dynamic type"/></figure>



<div style="height:26px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Creating a ScrollView with a Grid Layout</h2>



<p class="wp-block-paragraph">You can add any type of SwiftUI view to the ScrollView. For example LazyVStack, LazyHStack, LazyVGrid, or LazyHGrid. For example, we can make a vertical grid veritcally scrollable:</p>


<div class="wp-block-image">
<figure class="alignright is-resized"><img decoding="async" src="https://www.swiftyplace.com/wp-content/uploads/2023/08/scroll_view_grid-533x1024.jpg" alt="Example for SwiftUI ScrollView with grid layout using LazyVGrid" style="width:276px;height:531px"/></figure>
</div>


<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="struct ContentView: View {
    let columns = [GridItem(.adaptive(minimum: 75.00), spacing: 10)]
      var body: some View {
           ScrollView {
               LazyVGrid(columns: columns) {
                   ForEach(0x1f600...0x1f679, id: \.self) { value in
                       GroupBox {
                           Text(emoji(value))
                               .font(.largeTitle)
                               .fixedSize()
                           Text(String(format: &quot;%x&quot;, value))
                               .fixedSize()
                       }
                   }
               }
               .padding()
           }
      }
      private func emoji(_ value: Int) -&gt; String {
          guard let scalar = UnicodeScalar(value) else { return &quot;?&quot; }
          return String(Character(scalar))
      }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">struct</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ContentView</span><span style="color: #F6F6F4">: View {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> columns </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> [</span><span style="color: #97E1F1">GridItem</span><span style="color: #F6F6F4">(.</span><span style="color: #97E1F1">adaptive</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">minimum</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">75.00</span><span style="color: #F6F6F4">), </span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">10</span><span style="color: #F6F6F4">)]</span></span>
<span class="line"><span style="color: #F6F6F4">      </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> body: </span><span style="color: #F286C4">some</span><span style="color: #F6F6F4"> View {</span></span>
<span class="line"><span style="color: #F6F6F4">           ScrollView {</span></span>
<span class="line"><span style="color: #F6F6F4">               </span><span style="color: #97E1F1">LazyVGrid</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">columns</span><span style="color: #F6F6F4">: columns) {</span></span>
<span class="line"><span style="color: #F6F6F4">                   </span><span style="color: #97E1F1">ForEach</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">0x1f600</span><span style="color: #F286C4">...</span><span style="color: #BF9EEE">0x1f679</span><span style="color: #F6F6F4">, </span><span style="color: #97E1F1">id</span><span style="color: #F6F6F4">: \.</span><span style="color: #F286C4">self</span><span style="color: #F6F6F4">) { value </span><span style="color: #F286C4">in</span></span>
<span class="line"><span style="color: #F6F6F4">                       GroupBox {</span></span>
<span class="line"><span style="color: #F6F6F4">                           </span><span style="color: #97E1F1">Text</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">emoji</span><span style="color: #F6F6F4">(value))</span></span>
<span class="line"><span style="color: #F6F6F4">                               .</span><span style="color: #97E1F1">font</span><span style="color: #F6F6F4">(.largeTitle)</span></span>
<span class="line"><span style="color: #F6F6F4">                               .</span><span style="color: #97E1F1">fixedSize</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">                           </span><span style="color: #97E1F1">Text</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1; font-style: italic">String</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">format</span><span style="color: #F6F6F4">: </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">%x</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">, value))</span></span>
<span class="line"><span style="color: #F6F6F4">                               .</span><span style="color: #97E1F1">fixedSize</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">                       }</span></span>
<span class="line"><span style="color: #F6F6F4">                   }</span></span>
<span class="line"><span style="color: #F6F6F4">               }</span></span>
<span class="line"><span style="color: #F6F6F4">               .</span><span style="color: #97E1F1">padding</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">           }</span></span>
<span class="line"><span style="color: #F6F6F4">      }</span></span>
<span class="line"><span style="color: #F6F6F4">      </span><span style="color: #F286C4">private</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">func</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">emoji</span><span style="color: #F6F6F4">(</span><span style="color: #62E884">_</span><span style="color: #F6F6F4"> </span><span style="color: #FFB86C; font-style: italic">value</span><span style="color: #F6F6F4">: </span><span style="color: #97E1F1; font-style: italic">Int</span><span style="color: #F6F6F4">) </span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">String</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">          </span><span style="color: #F286C4">guard</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> scalar </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">UnicodeScalar</span><span style="color: #F6F6F4">(value) </span><span style="color: #F286C4">else</span><span style="color: #F6F6F4"> { </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">?</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4"> }</span></span>
<span class="line"><span style="color: #F6F6F4">          </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">String</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1; font-style: italic">Character</span><span style="color: #F6F6F4">(scalar))</span></span>
<span class="line"><span style="color: #F6F6F4">      }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<div style="height:38px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Example Data</h2>



<p class="wp-block-paragraph">Because you can create some great-looking UI with ScrollView, I am using more complex data, where I added images in the assets catalog (<a href="https://www.swiftyplace.com/blog/mastering-swiftui-image-view" target="_blank" rel="noopener">how to work with images</a>):</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="struct NatureInspiration: Identifiable {
    let name: String
    let imageName: String
    let description: String
    let id = UUID()

    static func examples() -&gt; [NatureInspiration] {
        [NatureInspiration(name: &quot;Desert&quot;,
                           imageName: &quot;desert&quot;,
                           description: &quot;A desert is a barren area of landscape where little precipitation occurs and, consequently, living conditions are hostile for plant and animal life.&quot;),
         ...
        ]
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">struct</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">NatureInspiration</span><span style="color: #F6F6F4">: Identifiable {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> name: </span><span style="color: #97E1F1; font-style: italic">String</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> imageName: </span><span style="color: #97E1F1; font-style: italic">String</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> description: </span><span style="color: #97E1F1; font-style: italic">String</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> id </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">UUID</span><span style="color: #F6F6F4">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">static</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">func</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">examples</span><span style="color: #F6F6F4">() </span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4"> [NatureInspiration] {</span></span>
<span class="line"><span style="color: #F6F6F4">        [</span><span style="color: #97E1F1">NatureInspiration</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">name</span><span style="color: #F6F6F4">: </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">Desert</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">                           </span><span style="color: #97E1F1">imageName</span><span style="color: #F6F6F4">: </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">desert</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">                           </span><span style="color: #97E1F1">description</span><span style="color: #F6F6F4">: </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">A desert is a barren area of landscape where little precipitation occurs and, consequently, living conditions are hostile for plant and animal life.</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">),</span></span>
<span class="line"><span style="color: #F6F6F4">         </span><span style="color: #F286C4">...</span></span>
<span class="line"><span style="color: #F6F6F4">        ]</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">I also defined 3 different cells for NatureInspiration to have some variety in the sample project. The following defines a Card view:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="struct InspirationCardView: View {

    let inspiration: NatureInspiration
    let padding: CGFloat = 10

    var body: some View {
        Image(inspiration.imageName)
            .resizable()
            .scaledToFit()
            .cornerRadius(10)
            .shadow(radius: 5)

            .overlay(alignment: .bottomTrailing, content: {
                Text(inspiration.name)
                    .bold()
                    .foregroundColor(Color.white)
                    .padding()
            })
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">struct</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">InspirationCardView</span><span style="color: #F6F6F4">: View {</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> inspiration: NatureInspiration</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> padding: CGFloat </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">10</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> body: </span><span style="color: #F286C4">some</span><span style="color: #F6F6F4"> View {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #97E1F1">Image</span><span style="color: #F6F6F4">(inspiration.imageName)</span></span>
<span class="line"><span style="color: #F6F6F4">            .</span><span style="color: #97E1F1">resizable</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">            .</span><span style="color: #97E1F1">scaledToFit</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">            .</span><span style="color: #97E1F1">cornerRadius</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">10</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">            .</span><span style="color: #97E1F1">shadow</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">radius</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">5</span><span style="color: #F6F6F4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">            .</span><span style="color: #97E1F1">overlay</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">alignment</span><span style="color: #F6F6F4">: .bottomTrailing, </span><span style="color: #97E1F1">content</span><span style="color: #F6F6F4">: {</span></span>
<span class="line"><span style="color: #F6F6F4">                </span><span style="color: #97E1F1">Text</span><span style="color: #F6F6F4">(inspiration.name)</span></span>
<span class="line"><span style="color: #F6F6F4">                    .</span><span style="color: #97E1F1">bold</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">                    .</span><span style="color: #97E1F1">foregroundColor</span><span style="color: #F6F6F4">(Color.white)</span></span>
<span class="line"><span style="color: #F6F6F4">                    .</span><span style="color: #97E1F1">padding</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">            })</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">The size of the images is adjusted to fit the available space by using the <code>resizable</code> modifier and <code>scaleToFit</code>.</p>



<div style="height:22px" aria-hidden="true" class="wp-block-spacer"></div>


<div class="gb-container gb-container-c5dedc2e">
<div class="gb-container gb-container-f7a433c7">
<div class="gb-container gb-container-7a8dc7a3">

<figure class="gb-block-image gb-block-image-f04fbbad"><a href="https://www.swiftyplace.com/free-swiftui-layout-cookbook" target="_blank" rel="noopener noreferrer"><img fetchpriority="high" decoding="async" width="640" height="500" class="gb-image gb-image-f04fbbad" src="http://www.swiftyplace.com/wp-content/uploads/2024/01/swiftui_roadmap_preview.webp" alt="swiftui roadmap " title="swiftui_roadmap_preview" srcset="http://www.swiftyplace.com/wp-content/uploads/2024/01/swiftui_roadmap_preview.webp 640w, http://www.swiftyplace.com/wp-content/uploads/2024/01/swiftui_roadmap_preview-300x234.webp 300w" sizes="(max-width: 640px) 100vw, 640px" /></a></figure>

</div>

<div class="gb-container gb-container-98352fe6">

<h2 class="gb-headline gb-headline-4aacd94c gb-headline-text">Feeling Lost in SwiftUI?</h2>



<p class="gb-headline gb-headline-5e6c4f85 gb-headline-text">This SwiftUI roadmap shows you what to learn next.</p>



<ul style="margin-top:0;margin-bottom:0;font-size:18px" class="wp-block-list">
<li>Key concepts at a glance</li>



<li>Spot your knowledge gaps</li>



<li>Guide your learning path</li>
</ul>


<div class="gb-container gb-container-34a8ad02">

<a class="gb-button gb-button-63e90e76 gb-button-blue" href="https://school.swiftyplace.com/f/swiftui-roadmap" target="_blank" rel="noopener noreferrer"><span class="gb-button-text">Get the FREE PDF</span><span class="gb-icon"><svg aria-hidden="true" role="img" height="1em" width="1em" viewBox="0 0 256 512" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"></path></svg></span></a>

</div>


<p class="gb-headline gb-headline-7ef80e86 gb-headline-text">Ideal for beginners and self-learners.</p>

</div>
</div>
</div>


<div style="height:34px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">How to change the Scrollable Axis to Horizontal</h2>



<p class="wp-block-paragraph">Scroll view has a parameter to change the scroll direction from the default vertical scrolling to horizontal. We also have to use a horizontal stack inside the ScrollView otherwise the layout directions don&#8217;t match. You could use LazyHStack or LazyHGrid.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="struct ContentView: View {
    let natureInspiration = NatureInspiration.examples()
    var body: some View {
        ScrollView(.horizontal) {
            LazyHStack(spacing: 10) {
                ForEach(natureInspiration) { inspiration in
                    InspirationCardView(inspiration: inspiration)
                }
            }
            .padding()
        }
        .frame(height: 200)
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">struct</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ContentView</span><span style="color: #F6F6F4">: View {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> natureInspiration </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> NatureInspiration.</span><span style="color: #97E1F1">examples</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> body: </span><span style="color: #F286C4">some</span><span style="color: #F6F6F4"> View {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #97E1F1">ScrollView</span><span style="color: #F6F6F4">(.horizontal) {</span></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #97E1F1">LazyHStack</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">10</span><span style="color: #F6F6F4">) {</span></span>
<span class="line"><span style="color: #F6F6F4">                </span><span style="color: #97E1F1">ForEach</span><span style="color: #F6F6F4">(natureInspiration) { inspiration </span><span style="color: #F286C4">in</span></span>
<span class="line"><span style="color: #F6F6F4">                    </span><span style="color: #97E1F1">InspirationCardView</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">inspiration</span><span style="color: #F6F6F4">: inspiration)</span></span>
<span class="line"><span style="color: #F6F6F4">                }</span></span>
<span class="line"><span style="color: #F6F6F4">            }</span></span>
<span class="line"><span style="color: #F6F6F4">            .</span><span style="color: #97E1F1">padding</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">        }</span></span>
<span class="line"><span style="color: #F6F6F4">        .</span><span style="color: #97E1F1">frame</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">height</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">200</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<div style="height:41px" aria-hidden="true" class="wp-block-spacer"></div>


<div class="wp-block-image">
<figure class="aligncenter is-resized"><img decoding="async" src="https://www.swiftyplace.com/wp-content/uploads/2023/08/scrollview_axis-1024x716.webp" alt="SwiftUI ScrollView examples with horizontal and vertical axis" style="width:754px;height:527px"/></figure>
</div>


<div style="height:62px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Complex Layout Example</h2>



<p class="wp-block-paragraph">We can combine multiple ScrollViews together to create a complex layout similar to UICollectionView. It is possible to add ScrollView as a child view to a parent ScrollView. You can create sections with horizontal scroll views by adding the following to the parent view:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="ScrollView {
    ScrollView(.horizontal) {
        LazyHStack(spacing: 10) {
            ForEach(natureInspiration) { inspiration in
                InspirationCardView(inspiration: inspiration)
            }
        }

        // Add more sections
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">ScrollView {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #97E1F1">ScrollView</span><span style="color: #F6F6F4">(.horizontal) {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #97E1F1">LazyHStack</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">10</span><span style="color: #F6F6F4">) {</span></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #97E1F1">ForEach</span><span style="color: #F6F6F4">(natureInspiration) { inspiration </span><span style="color: #F286C4">in</span></span>
<span class="line"><span style="color: #F6F6F4">                </span><span style="color: #97E1F1">InspirationCardView</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">inspiration</span><span style="color: #F6F6F4">: inspiration)</span></span>
<span class="line"><span style="color: #F6F6F4">            }</span></span>
<span class="line"><span style="color: #F6F6F4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #7B7F8B">// Add more sections</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<div style="height:22px" aria-hidden="true" class="wp-block-spacer"></div>


<div class="wp-block-image">
<figure class="alignright is-resized"><img decoding="async" src="https://www.swiftyplace.com/wp-content/uploads/2023/08/swiftui_scrollview_complex_layout-515x1024.jpg" alt="" style="width:376px;height:747px"/></figure>
</div>


<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-highlight-color:rgba(251, 251, 239, 0.2);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="struct ContentView: View {
    @State private var inspiration = NatureInspiration.examples()
    var body: some View {
        NavigationView {
            ScrollView {
                LazyVStack(alignment: .leading) {
                    ScrollView(.horizontal) {
                        LazyHStack {
                            ForEach(inspiration) { inspiration in
                                InspirationCardView(inspiration: inspiration)
                            }
                        }
                        .padding()
                    }
                    .frame(height: 180)

                    Section {
                        InspirationGridSectionView()
                    } header: {
                        Text(&quot;Second Section&quot;)
                            .font(.headline)
                    }

                    LazyVStack(alignment: .leading) {
                        Text(&quot;Third Section&quot;)
                            .font(.headline)
                        ForEach(inspiration) { inspiration in
                            InspirationRowView(inspiration: inspiration)
                        }
                    }
                    .padding()
                }
            }
            .navigationTitle(&quot;Inspirations&quot;)
        }
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">struct</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ContentView</span><span style="color: #F6F6F4">: View {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">@State</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">private</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> inspiration </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> NatureInspiration.</span><span style="color: #97E1F1">examples</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> body: </span><span style="color: #F286C4">some</span><span style="color: #F6F6F4"> View {</span></span>
<span class="line"><span style="color: #F6F6F4">        NavigationView {</span></span>
<span class="line"><span style="color: #F6F6F4">            ScrollView {</span></span>
<span class="line"><span style="color: #F6F6F4">                </span><span style="color: #97E1F1">LazyVStack</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">alignment</span><span style="color: #F6F6F4">: .leading) {</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">                    </span><span style="color: #97E1F1">ScrollView</span><span style="color: #F6F6F4">(.horizontal) {</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">                        LazyHStack {</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">                            </span><span style="color: #97E1F1">ForEach</span><span style="color: #F6F6F4">(inspiration) { inspiration </span><span style="color: #F286C4">in</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">                                </span><span style="color: #97E1F1">InspirationCardView</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">inspiration</span><span style="color: #F6F6F4">: inspiration)</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">                            }</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">                        }</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">                        .</span><span style="color: #97E1F1">padding</span><span style="color: #F6F6F4">()</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">                    }</span></span>
<span class="line"><span style="color: #F6F6F4">                    .</span><span style="color: #97E1F1">frame</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">height</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">180</span><span style="color: #F6F6F4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">                    Section {</span></span>
<span class="line"><span style="color: #F6F6F4">                        </span><span style="color: #97E1F1">InspirationGridSectionView</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">                    } header</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">                        </span><span style="color: #97E1F1">Text</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">Second Section</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">                            .</span><span style="color: #97E1F1">font</span><span style="color: #F6F6F4">(.headline)</span></span>
<span class="line"><span style="color: #F6F6F4">                    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">                    </span><span style="color: #97E1F1">LazyVStack</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">alignment</span><span style="color: #F6F6F4">: .leading) {</span></span>
<span class="line"><span style="color: #F6F6F4">                        </span><span style="color: #97E1F1">Text</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">Third Section</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">                            .</span><span style="color: #97E1F1">font</span><span style="color: #F6F6F4">(.headline)</span></span>
<span class="line"><span style="color: #F6F6F4">                        </span><span style="color: #97E1F1">ForEach</span><span style="color: #F6F6F4">(inspiration) { inspiration </span><span style="color: #F286C4">in</span></span>
<span class="line"><span style="color: #F6F6F4">                            </span><span style="color: #97E1F1">InspirationRowView</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">inspiration</span><span style="color: #F6F6F4">: inspiration)</span></span>
<span class="line"><span style="color: #F6F6F4">                        }</span></span>
<span class="line"><span style="color: #F6F6F4">                    }</span></span>
<span class="line"><span style="color: #F6F6F4">                    .</span><span style="color: #97E1F1">padding</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">                }</span></span>
<span class="line"><span style="color: #F6F6F4">            }</span></span>
<span class="line"><span style="color: #F6F6F4">            .</span><span style="color: #97E1F1">navigationTitle</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">Inspirations</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">        }</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<div style="height:55px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">How to Customize the Scroll Behaviour</h2>



<h3 class="wp-block-heading">How do I disable scrolling?</h3>



<p class="wp-block-paragraph">With iOS 16, we can now disable scrolling for any scrollable component including ScrollView, List, and TextEditor. Use the new modifier scrollDisabled(_:). You can also dynamically enable/disable this behaviour.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="ScrollView {
   ...
}
.scrollDisabled(true)" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">ScrollView {</span></span>
<span class="line"><span style="color: #F6F6F4">   </span><span style="color: #F286C4">...</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"><span style="color: #F6F6F4">.</span><span style="color: #97E1F1">scrollDisabled</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">true</span><span style="color: #F6F6F4">)</span></span></code></pre></div>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">How to hide the Scroll Indicator</h3>



<p class="wp-block-paragraph">The scroll view displays per default scroll indicators. If you want to hide the scroll indicator, you can pass false for the argument showsIndicators:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="ScrollView(showsIndicators: false) {
   ...
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #97E1F1">ScrollView</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">showsIndicators</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">false</span><span style="color: #F6F6F4">) {</span></span>
<span class="line"><span style="color: #F6F6F4">   </span><span style="color: #F286C4">...</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">This changed to scrollIndicators for iOS 16 and macOS 13:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="ScrollView {
   ...
}.scrollIndicators(.hidden)" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">ScrollView {</span></span>
<span class="line"><span style="color: #F6F6F4">   </span><span style="color: #F286C4">...</span></span>
<span class="line"><span style="color: #F6F6F4">}.</span><span style="color: #97E1F1">scrollIndicators</span><span style="color: #F6F6F4">(.hidden)</span></span></code></pre></div>



<div style="height:34px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">How do I programmatically flash the ScrollView indicator?</h3>



<p class="wp-block-paragraph">New with iOS 17 and macOS 14, you can now programmatically flash the indictor. In the following is an example where the indicator is flashing when the scroll view appears:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(1 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="ScrollView {
   ...
}
.scrollIndicatorsFlash(onAppear: true)" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">ScrollView {</span></span>
<span class="line"><span style="color: #F6F6F4">   </span><span style="color: #F286C4">...</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"><span style="color: #F6F6F4">.</span><span style="color: #97E1F1">scrollIndicatorsFlash</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">onAppear</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">true</span><span style="color: #F6F6F4">)</span></span></code></pre></div>



<div style="height:17px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">If you want to trigger the scroll indicator flashing at a specific time, you can use the <code>scrollIndicatorsFlash(trigger:</code>). In the following example, the indicator flashes when ever the value of count changes:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(1 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="@State private var count: Int = 0

ScrollView {
   ...
}
.scrollIndicatorsFlash(trigger: count)" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">@State</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">private</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> count: </span><span style="color: #97E1F1; font-style: italic">Int</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">0</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">ScrollView {</span></span>
<span class="line"><span style="color: #F6F6F4">   </span><span style="color: #F286C4">...</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"><span style="color: #F6F6F4">.</span><span style="color: #97E1F1">scrollIndicatorsFlash</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">trigger</span><span style="color: #F6F6F4">: count)</span></span></code></pre></div>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">ScrollView Clipping Behaviour</h3>



<p class="wp-block-paragraph">SwiftUI ScrollView will clip its content when it moves out of its visible area. You can disabled clipping in iOS 17 with:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);--cbp-line-highlight-color:rgba(251, 251, 239, 0.2);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="ScrollView(.horizontal) {
    HStack(spacing: 10) {
        ForEach(natureInspiration) { inspiration in
            InspirationImageView(inspiration: inspiration)
                .frame(width: 300)
        }
    }
}
.scrollClipDisabled()
" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #97E1F1">ScrollView</span><span style="color: #F6F6F4">(.horizontal) {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #97E1F1">HStack</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">10</span><span style="color: #F6F6F4">) {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #97E1F1">ForEach</span><span style="color: #F6F6F4">(natureInspiration) { inspiration </span><span style="color: #F286C4">in</span></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #97E1F1">InspirationImageView</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">inspiration</span><span style="color: #F6F6F4">: inspiration)</span></span>
<span class="line"><span style="color: #F6F6F4">                .</span><span style="color: #97E1F1">frame</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">width</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">300</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">        }</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">.</span><span style="color: #97E1F1">scrollClipDisabled</span><span style="color: #F6F6F4">()</span></span>
<span class="line"></span></code></pre></div>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" width="1024" height="430" src="https://www.swiftyplace.com/wp-content/uploads/2023/10/scrollview_clipping_disabled.webp" alt="SwiftUI Scrollview with clipping disabled" class="wp-image-3577" srcset="http://www.swiftyplace.com/wp-content/uploads/2023/10/scrollview_clipping_disabled.webp 1024w, http://www.swiftyplace.com/wp-content/uploads/2023/10/scrollview_clipping_disabled-300x126.webp 300w, http://www.swiftyplace.com/wp-content/uploads/2023/10/scrollview_clipping_disabled-768x323.webp 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Programmatic scrolling with ScrollViewReader</h3>



<p class="wp-block-paragraph">With iOS 14 and macOS 11, ScrollViewReader was introduced, which gives you the ScrollViewProxy. Call scrollTo(_ id: ID, anchor: UnitPoint) to programmatically scroll to the view with the provided id. I</p>



<p class="wp-block-paragraph">n the following example, I added an id to the last text view in the scroll view. At the top of the scroll view, you can use the button to scroll down. Programmatic scrolling is done by calling the proxis scrollTo(bottomID). Because I make the change in a withAnimation block, the scrolling animates nicely.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="struct ContentView: View {

@Namespace var bottomID

var body: some View {
    ScrollViewReader { proxy in
        ScrollView {
            Button(&quot;Scroll to Bottom&quot;) {
                withAnimation {
                    proxy.scrollTo(bottomID)
                }
            }

            // main content

            Text(&quot;You reached the bottom&quot;)
                .id(bottomID)
        }
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">struct</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ContentView</span><span style="color: #F6F6F4">: View {</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">@Namespace</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> bottomID</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> body: </span><span style="color: #F286C4">some</span><span style="color: #F6F6F4"> View {</span></span>
<span class="line"><span style="color: #F6F6F4">    ScrollViewReader { proxy </span><span style="color: #F286C4">in</span></span>
<span class="line"><span style="color: #F6F6F4">        ScrollView {</span></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #97E1F1">Button</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">Scroll to Bottom</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">) {</span></span>
<span class="line"><span style="color: #F6F6F4">                withAnimation {</span></span>
<span class="line"><span style="color: #F6F6F4">                    proxy.</span><span style="color: #97E1F1">scrollTo</span><span style="color: #F6F6F4">(bottomID)</span></span>
<span class="line"><span style="color: #F6F6F4">                }</span></span>
<span class="line"><span style="color: #F6F6F4">            }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #7B7F8B">// main content</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #97E1F1">Text</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">You reached the bottom</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">                .</span><span style="color: #97E1F1">id</span><span style="color: #F6F6F4">(bottomID)</span></span>
<span class="line"><span style="color: #F6F6F4">        }</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<div style="height:55px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Scrolling in a dynamic list</h3>



<p class="wp-block-paragraph">In case you have a dynamic list with many data rows, we can set the id like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="ScrollViewReader { proxy in
      ScrollView {
         ForEach(natureInspiration) { inspiration in
               InspirationRowView(inspiration: inspiration)
                  .id(inspiration.id)
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">ScrollViewReader { proxy </span><span style="color: #F286C4">in</span></span>
<span class="line"><span style="color: #F6F6F4">      ScrollView {</span></span>
<span class="line"><span style="color: #F6F6F4">         </span><span style="color: #97E1F1">ForEach</span><span style="color: #F6F6F4">(natureInspiration) { inspiration </span><span style="color: #F286C4">in</span></span>
<span class="line"><span style="color: #F6F6F4">               </span><span style="color: #97E1F1">InspirationRowView</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">inspiration</span><span style="color: #F6F6F4">: inspiration)</span></span>
<span class="line"><span style="color: #F6F6F4">                  .</span><span style="color: #97E1F1">id</span><span style="color: #F6F6F4">(inspiration.id)</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<div style="height:29px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">You can then scroll to a specific row by using the data´s id:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="Button(&quot;Scroll to selected inspiration&quot;) {
    withAnimation {
        proxy.scrollTo(selectedInspiration.id, anchor: .top)
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #97E1F1">Button</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">Scroll to selected inspiration</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">) {</span></span>
<span class="line"><span style="color: #F6F6F4">    withAnimation {</span></span>
<span class="line"><span style="color: #F6F6F4">        proxy.</span><span style="color: #97E1F1">scrollTo</span><span style="color: #F6F6F4">(selectedInspiration.id, </span><span style="color: #97E1F1">anchor</span><span style="color: #F6F6F4">: .top)</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<div style="height:29px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">Notice that I used the anchor parameter, where you have the options for top, center, and bottom. The default anchor is center. If you set an anchor of top, the top of the scroll views frame is aligned to the top of the view you want to scroll to. If the scrollable content region is not large enough. For example, scroll to the last cell and use a top anchor, the scroll view will not scroll fully to the defined position.</p>


<div class="wp-block-image">
<figure class="alignright is-resized"><img decoding="async" src="https://www.swiftyplace.com/wp-content/uploads/2023/08/scrollview_programmatically_scoll-543x1024.jpg" alt="Example implementation for scroll to in a SwiftUI ScrollView" style="width:366px;height:691px"/></figure>
</div>


<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-highlight-color:rgba(251, 251, 239, 0.2);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="struct ContentView: View {
let natureInspiration = NatureInspiration.examples()
@Namespace var topID
@Namespace var bottomID
@State private var selectedInspirationId: UUID? = nil

  var body: some View {
     ScrollViewReader { proxy in
        ScrollView {
            Button(&quot;Scroll to Bottom&quot;) {
                withAnimation {
                    proxy.scrollTo(bottomID)
                }
            }
            .buttonStyle(.bordered)
            .id(topID)

            LazyVStack(alignment: .leading, spacing: 10) {
                ForEach(natureInspiration) { inspiration in
                    InspirationRowView(inspiration: inspiration)
                        .foregroundColor(forgroundColor(for: inspiration))
                        .background(
                            RoundedRectangle(cornerRadius: 5)
                                .fill(color(for: inspiration)))
                        .id(inspiration.id)
                        .onTapGesture {
                            tapped(on: inspiration)
                        }
                    Divider()
                }
            }.padding()
        }
     }
    .overlay {
        VStack(spacing: 0) {
            Rectangle().stroke(Color.pink, lineWidth: 2)
            Rectangle().stroke(Color.pink, lineWidth: 2)
        }
    }
  }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">struct</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ContentView</span><span style="color: #F6F6F4">: View {</span></span>
<span class="line"><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> natureInspiration </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> NatureInspiration.</span><span style="color: #97E1F1">examples</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F286C4">@Namespace</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> topID</span></span>
<span class="line"><span style="color: #F286C4">@Namespace</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> bottomID</span></span>
<span class="line"><span style="color: #F286C4">@State</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">private</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> selectedInspirationId: UUID</span><span style="color: #F286C4">?</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">nil</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> body: </span><span style="color: #F286C4">some</span><span style="color: #F6F6F4"> View {</span></span>
<span class="line"><span style="color: #F6F6F4">     ScrollViewReader { proxy </span><span style="color: #F286C4">in</span></span>
<span class="line"><span style="color: #F6F6F4">        ScrollView {</span></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #97E1F1">Button</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">Scroll to Bottom</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">) {</span></span>
<span class="line"><span style="color: #F6F6F4">                withAnimation {</span></span>
<span class="line"><span style="color: #F6F6F4">                    proxy.</span><span style="color: #97E1F1">scrollTo</span><span style="color: #F6F6F4">(bottomID)</span></span>
<span class="line"><span style="color: #F6F6F4">                }</span></span>
<span class="line"><span style="color: #F6F6F4">            }</span></span>
<span class="line"><span style="color: #F6F6F4">            .</span><span style="color: #97E1F1">buttonStyle</span><span style="color: #F6F6F4">(.bordered)</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">            .</span><span style="color: #97E1F1">id</span><span style="color: #F6F6F4">(topID)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #97E1F1">LazyVStack</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">alignment</span><span style="color: #F6F6F4">: .leading, </span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">10</span><span style="color: #F6F6F4">) {</span></span>
<span class="line"><span style="color: #F6F6F4">                </span><span style="color: #97E1F1">ForEach</span><span style="color: #F6F6F4">(natureInspiration) { inspiration </span><span style="color: #F286C4">in</span></span>
<span class="line"><span style="color: #F6F6F4">                    </span><span style="color: #97E1F1">InspirationRowView</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">inspiration</span><span style="color: #F6F6F4">: inspiration)</span></span>
<span class="line"><span style="color: #F6F6F4">                        .</span><span style="color: #97E1F1">foregroundColor</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">forgroundColor</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">for</span><span style="color: #F6F6F4">: inspiration))</span></span>
<span class="line"><span style="color: #F6F6F4">                        .</span><span style="color: #97E1F1">background</span><span style="color: #F6F6F4">(</span></span>
<span class="line"><span style="color: #F6F6F4">                            </span><span style="color: #97E1F1">RoundedRectangle</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">cornerRadius</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">5</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">                                .</span><span style="color: #97E1F1">fill</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">color</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">for</span><span style="color: #F6F6F4">: inspiration)))</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">                        .</span><span style="color: #97E1F1">id</span><span style="color: #F6F6F4">(inspiration.id)</span></span>
<span class="line"><span style="color: #F6F6F4">                        .onTapGesture {</span></span>
<span class="line"><span style="color: #F6F6F4">                            </span><span style="color: #97E1F1">tapped</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">on</span><span style="color: #F6F6F4">: inspiration)</span></span>
<span class="line"><span style="color: #F6F6F4">                        }</span></span>
<span class="line"><span style="color: #F6F6F4">                    </span><span style="color: #97E1F1">Divider</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">                }</span></span>
<span class="line"><span style="color: #F6F6F4">            }.</span><span style="color: #97E1F1">padding</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">        }</span></span>
<span class="line"><span style="color: #F6F6F4">     }</span></span>
<span class="line"><span style="color: #F6F6F4">    .overlay {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #97E1F1">VStack</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">0</span><span style="color: #F6F6F4">) {</span></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #97E1F1">Rectangle</span><span style="color: #F6F6F4">().</span><span style="color: #97E1F1">stroke</span><span style="color: #F6F6F4">(Color.pink, </span><span style="color: #97E1F1">lineWidth</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">2</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #97E1F1">Rectangle</span><span style="color: #F6F6F4">().</span><span style="color: #97E1F1">stroke</span><span style="color: #F6F6F4">(Color.pink, </span><span style="color: #97E1F1">lineWidth</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">2</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">        }</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">  }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<div style="height:37px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">In order to see the alignment better, I added an overlay with red lines. You can see the frame of the scroll view and the center line.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="ScrollViewReader { proxy in
    ScrollView {
        ...
    }
}
.overlay {
    VStack(spacing: 0) {
        Rectangle().stroke(Color.pink, lineWidth: 2)
        Rectangle().stroke(Color.pink, lineWidth: 2)
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">ScrollViewReader { proxy </span><span style="color: #F286C4">in</span></span>
<span class="line"><span style="color: #F6F6F4">    ScrollView {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #F286C4">...</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"><span style="color: #F6F6F4">.overlay {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #97E1F1">VStack</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">0</span><span style="color: #F6F6F4">) {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #97E1F1">Rectangle</span><span style="color: #F6F6F4">().</span><span style="color: #97E1F1">stroke</span><span style="color: #F6F6F4">(Color.pink, </span><span style="color: #97E1F1">lineWidth</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">2</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #97E1F1">Rectangle</span><span style="color: #F6F6F4">().</span><span style="color: #97E1F1">stroke</span><span style="color: #F6F6F4">(Color.pink, </span><span style="color: #97E1F1">lineWidth</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">2</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<div style="height:26px" aria-hidden="true" class="wp-block-spacer"></div>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" src="https://www.swiftyplace.com/wp-content/uploads/2023/08/scrollview_scroll_anchor.webp" alt="SwiftUI scrollview examples where ScrollViewReader is used to scroll to particular row with differnt anchor settings"/><figcaption class="wp-element-caption">When you tap on a button the list scrolls programmatically to the selected row (highlighted in grey).</figcaption></figure>
</div>


<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">How to get ScrollView offset in SwiftUI?</h3>



<p class="wp-block-paragraph">ScrollView has a native way to give you the content offset with iOS 17 and macOS 14. You need to use <strong>scrollPosition</strong> modifier and <strong>scrollTargetLayout</strong>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="struct Emoji: Identifiable {
    let value: Int
    
    var emojiSting: String {
        guard let scalar = UnicodeScalar(value) else { return &quot;?&quot; }
        return String(Character(scalar))
    }
    
    var valueString: String {
        String(format: &quot;%x&quot;, value)
    }
    
    var id: Int {
        return value
    }
    
    static func example() -&gt; Emoji {
         Emoji(value: 0x1f600) 
    }
    
    static func examples() -&gt; [Emoji] {
        let values = 0x1f600...0x1f64f
        return values.map {  Emoji(value: $0) }
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">struct</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Emoji</span><span style="color: #F6F6F4">: Identifiable {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> value: </span><span style="color: #97E1F1; font-style: italic">Int</span></span>
<span class="line"><span style="color: #F6F6F4">    </span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> emojiSting: </span><span style="color: #97E1F1; font-style: italic">String</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #F286C4">guard</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> scalar </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">UnicodeScalar</span><span style="color: #F6F6F4">(value) </span><span style="color: #F286C4">else</span><span style="color: #F6F6F4"> { </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">?</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4"> }</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">String</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1; font-style: italic">Character</span><span style="color: #F6F6F4">(scalar))</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">    </span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> valueString: </span><span style="color: #97E1F1; font-style: italic">String</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #97E1F1; font-style: italic">String</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">format</span><span style="color: #F6F6F4">: </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">%x</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">, value)</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">    </span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> id: </span><span style="color: #97E1F1; font-style: italic">Int</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> value</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">    </span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">static</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">func</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">example</span><span style="color: #F6F6F4">() </span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4"> Emoji {</span></span>
<span class="line"><span style="color: #F6F6F4">         </span><span style="color: #97E1F1">Emoji</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">value</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">0x1f600</span><span style="color: #F6F6F4">) </span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">    </span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">static</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">func</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">examples</span><span style="color: #F6F6F4">() </span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4"> [Emoji] {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> values </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">0x1f600</span><span style="color: #F286C4">...</span><span style="color: #BF9EEE">0x1f64f</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> values.</span><span style="color: #97E1F1">map</span><span style="color: #F6F6F4"> {  </span><span style="color: #97E1F1">Emoji</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">value</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE; font-style: italic">$0</span><span style="color: #F6F6F4">) }</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph"></p>



<div style="height:21px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);--cbp-line-highlight-color:rgba(251, 251, 239, 0.2);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="struct ContentView: View {
    
    @State private var scrolledID: Int? = nil
    let emojis: [Emoji] = Emoji.examples()
    
    var body: some View {
        ScrollView {
            LazyVStack {
                ForEach(emojis) { emoji in
                    GroupBox {
                        Text(&quot;\(emoji.id)&quot;)
                        Text(emoji.emojiSting)
                            .font(.largeTitle)
                            .frame(maxWidth: .infinity)
                    }
                }
            }
            .padding()
            // need this to update scrollid when user manually scrolls
            .scrollTargetLayout() 
        }
        .scrollPosition(id: $scrolledID, anchor: .bottom)
        .safeAreaInset(edge: .bottom) {
            Text(&quot;scrollposition \(scrolledID ?? 0)&quot;)
                .foregroundStyle(.indigo)
                .font(.title)
                .padding(.top)
                .frame(maxWidth: .infinity)
                .background(.thinMaterial)
        }
        .background(Color.indigo)
    }
}
" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">struct</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ContentView</span><span style="color: #F6F6F4">: View {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">@State</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">private</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> scrolledID: </span><span style="color: #97E1F1; font-style: italic">Int</span><span style="color: #F286C4">?</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">nil</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> emojis: [Emoji] </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> Emoji.</span><span style="color: #97E1F1">examples</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">    </span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> body: </span><span style="color: #F286C4">some</span><span style="color: #F6F6F4"> View {</span></span>
<span class="line"><span style="color: #F6F6F4">        ScrollView {</span></span>
<span class="line"><span style="color: #F6F6F4">            LazyVStack {</span></span>
<span class="line"><span style="color: #F6F6F4">                </span><span style="color: #97E1F1">ForEach</span><span style="color: #F6F6F4">(emojis) { emoji </span><span style="color: #F286C4">in</span></span>
<span class="line"><span style="color: #F6F6F4">                    GroupBox {</span></span>
<span class="line"><span style="color: #F6F6F4">                        </span><span style="color: #97E1F1">Text</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&quot;</span><span style="color: #F286C4">\(</span><span style="color: #E7EE98">emoji.</span><span style="color: #F6F6F4">id</span><span style="color: #F286C4">)</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">                        </span><span style="color: #97E1F1">Text</span><span style="color: #F6F6F4">(emoji.emojiSting)</span></span>
<span class="line"><span style="color: #F6F6F4">                            .</span><span style="color: #97E1F1">font</span><span style="color: #F6F6F4">(.largeTitle)</span></span>
<span class="line"><span style="color: #F6F6F4">                            .</span><span style="color: #97E1F1">frame</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">maxWidth</span><span style="color: #F6F6F4">: .</span><span style="color: #BF9EEE">infinity</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">                    }</span></span>
<span class="line"><span style="color: #F6F6F4">                }</span></span>
<span class="line"><span style="color: #F6F6F4">            }</span></span>
<span class="line"><span style="color: #F6F6F4">            .</span><span style="color: #97E1F1">padding</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #7B7F8B">// need this to update scrollid when user manually scrolls</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">            .</span><span style="color: #97E1F1">scrollTargetLayout</span><span style="color: #F6F6F4">() </span></span>
<span class="line"><span style="color: #F6F6F4">        }</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">        .</span><span style="color: #97E1F1">scrollPosition</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">id</span><span style="color: #F6F6F4">: $scrolledID, </span><span style="color: #97E1F1">anchor</span><span style="color: #F6F6F4">: .bottom)</span></span>
<span class="line"><span style="color: #F6F6F4">        .</span><span style="color: #97E1F1">safeAreaInset</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">edge</span><span style="color: #F6F6F4">: .bottom) {</span></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #97E1F1">Text</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">scrollposition </span><span style="color: #F286C4">\(</span><span style="color: #E7EE98">scrolledID </span><span style="color: #F286C4">??</span><span style="color: #E7EE98"> </span><span style="color: #BF9EEE">0</span><span style="color: #F286C4">)</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">                .</span><span style="color: #97E1F1">foregroundStyle</span><span style="color: #F6F6F4">(.indigo)</span></span>
<span class="line"><span style="color: #F6F6F4">                .</span><span style="color: #97E1F1">font</span><span style="color: #F6F6F4">(.title)</span></span>
<span class="line"><span style="color: #F6F6F4">                .</span><span style="color: #97E1F1">padding</span><span style="color: #F6F6F4">(.top)</span></span>
<span class="line"><span style="color: #F6F6F4">                .</span><span style="color: #97E1F1">frame</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">maxWidth</span><span style="color: #F6F6F4">: .</span><span style="color: #BF9EEE">infinity</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">                .</span><span style="color: #97E1F1">background</span><span style="color: #F6F6F4">(.thinMaterial)</span></span>
<span class="line"><span style="color: #F6F6F4">        }</span></span>
<span class="line"><span style="color: #F6F6F4">        .</span><span style="color: #97E1F1">background</span><span style="color: #F6F6F4">(Color.indigo)</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span></code></pre></div>



<div style="height:39px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">I am setting the scroll position to bottom in this example. Therefore, the <code>scrollID</code> property will give me the emoji&#8217;s id at the bottom of the scroll view. I am showing the emoji ID scroll position at the bottom of the screen with the <code>safeAreaInset</code> modifier:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" width="1024" height="917" src="https://www.swiftyplace.com/wp-content/uploads/2023/10/scrollview_offset.webp" alt="example of scrollview to get the scroll offset" class="wp-image-3580" style="width:570px;height:539px" srcset="http://www.swiftyplace.com/wp-content/uploads/2023/10/scrollview_offset.webp 1024w, http://www.swiftyplace.com/wp-content/uploads/2023/10/scrollview_offset-300x269.webp 300w, http://www.swiftyplace.com/wp-content/uploads/2023/10/scrollview_offset-768x688.webp 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">How to pin a section header to the top of a scroll view?</h3>



<p class="wp-block-paragraph">You can use a LazyVStack inside a ScrollView and specify its argument pinnedViews, which has the option to use section headers or footers:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="ScrollView {
    LazyVStack(alignment: .leading, spacing: 10, pinnedViews: .sectionHeaders) {
        Section {
            ForEach(inspiration) { inspiration in
                InspirationRowView(inspiration: inspiration)
            }
        } header: {
            SectionHeaderView(title: &quot;First Section&quot;)
        }
        ....
    }

}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">ScrollView {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #97E1F1">LazyVStack</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">alignment</span><span style="color: #F6F6F4">: .leading, </span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">10</span><span style="color: #F6F6F4">, </span><span style="color: #97E1F1">pinnedViews</span><span style="color: #F6F6F4">: .sectionHeaders) {</span></span>
<span class="line"><span style="color: #F6F6F4">        Section {</span></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #97E1F1">ForEach</span><span style="color: #F6F6F4">(inspiration) { inspiration </span><span style="color: #F286C4">in</span></span>
<span class="line"><span style="color: #F6F6F4">                </span><span style="color: #97E1F1">InspirationRowView</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">inspiration</span><span style="color: #F6F6F4">: inspiration)</span></span>
<span class="line"><span style="color: #F6F6F4">            }</span></span>
<span class="line"><span style="color: #F6F6F4">        } header</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #97E1F1">SectionHeaderView</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">title</span><span style="color: #F6F6F4">: </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">First Section</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">        }</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #F286C4">....</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<div style="height:31px" aria-hidden="true" class="wp-block-spacer"></div>


<div class="gb-container gb-container-c5dedc2e">
<div class="gb-container gb-container-f7a433c7">
<div class="gb-container gb-container-7a8dc7a3">

<figure class="gb-block-image gb-block-image-f04fbbad"><a href="https://www.swiftyplace.com/free-swiftui-layout-cookbook" target="_blank" rel="noopener noreferrer"><img fetchpriority="high" decoding="async" width="640" height="500" class="gb-image gb-image-f04fbbad" src="http://www.swiftyplace.com/wp-content/uploads/2024/01/swiftui_roadmap_preview.webp" alt="swiftui roadmap " title="swiftui_roadmap_preview" srcset="http://www.swiftyplace.com/wp-content/uploads/2024/01/swiftui_roadmap_preview.webp 640w, http://www.swiftyplace.com/wp-content/uploads/2024/01/swiftui_roadmap_preview-300x234.webp 300w" sizes="(max-width: 640px) 100vw, 640px" /></a></figure>

</div>

<div class="gb-container gb-container-98352fe6">

<h2 class="gb-headline gb-headline-4aacd94c gb-headline-text">Feeling Lost in SwiftUI?</h2>



<p class="gb-headline gb-headline-5e6c4f85 gb-headline-text">This SwiftUI roadmap shows you what to learn next.</p>



<ul style="margin-top:0;margin-bottom:0;font-size:18px" class="wp-block-list">
<li>Key concepts at a glance</li>



<li>Spot your knowledge gaps</li>



<li>Guide your learning path</li>
</ul>


<div class="gb-container gb-container-34a8ad02">

<a class="gb-button gb-button-63e90e76 gb-button-blue" href="https://school.swiftyplace.com/f/swiftui-roadmap" target="_blank" rel="noopener noreferrer"><span class="gb-button-text">Get the FREE PDF</span><span class="gb-icon"><svg aria-hidden="true" role="img" height="1em" width="1em" viewBox="0 0 256 512" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"></path></svg></span></a>

</div>


<p class="gb-headline gb-headline-7ef80e86 gb-headline-text">Ideal for beginners and self-learners.</p>

</div>
</div>
</div>


<div style="height:36px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading">Paging Behaviour</h3>



<p class="wp-block-paragraph">Scroll views very commonly have page behavior, which means that when the user releases scrolling the view snaps into the next page position. This is now finally supported with iOS 17. </p>



<p class="wp-block-paragraph">You can use the <code>scrollTargetBehavior</code> modifier and set it to view aligned. Alternatively, you can use a paging behaviour. </p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(2 * 0.6 * 1rem);--cbp-line-highlight-color:rgba(251, 251, 239, 0.2);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="struct PagingScrollView: View {
    let natureInspiration = NatureInspiration.examples()
    
    let rows = [
        GridItem(.fixed(100), spacing: 5),
        GridItem(.fixed(100), spacing: 5),
        GridItem(.fixed(100), spacing: 5)
    ]
    
    var body: some View {
        ScrollView(.horizontal) {
            LazyHGrid(rows: rows, alignment: .top, spacing: 15) {
                ForEach(natureInspiration) { inspiration in
                    InspirationRowView(inspiration: inspiration)
                        .containerRelativeFrame(.horizontal,
                                                 count: 8,
                                                 span: 7,
                                                 spacing: 15,
                                                 alignment: .leading)
                }
            }
            .scrollTargetLayout(). // tells the scrollview to use these views for the alignment
        }
        .contentMargins(.horizontal, 20)
        .scrollBounceBehavior(.always)
        .scrollTargetBehavior(.viewAligned) // paging behaviour
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">struct</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">PagingScrollView</span><span style="color: #F6F6F4">: View {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> natureInspiration </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> NatureInspiration.</span><span style="color: #97E1F1">examples</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">    </span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">let</span><span style="color: #F6F6F4"> rows </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> [</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #97E1F1">GridItem</span><span style="color: #F6F6F4">(.</span><span style="color: #97E1F1">fixed</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">100</span><span style="color: #F6F6F4">), </span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">5</span><span style="color: #F6F6F4">),</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #97E1F1">GridItem</span><span style="color: #F6F6F4">(.</span><span style="color: #97E1F1">fixed</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">100</span><span style="color: #F6F6F4">), </span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">5</span><span style="color: #F6F6F4">),</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #97E1F1">GridItem</span><span style="color: #F6F6F4">(.</span><span style="color: #97E1F1">fixed</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">100</span><span style="color: #F6F6F4">), </span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">5</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">    ]</span></span>
<span class="line"><span style="color: #F6F6F4">    </span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">var</span><span style="color: #F6F6F4"> body: </span><span style="color: #F286C4">some</span><span style="color: #F6F6F4"> View {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #97E1F1">ScrollView</span><span style="color: #F6F6F4">(.horizontal) {</span></span>
<span class="line"><span style="color: #F6F6F4">            </span><span style="color: #97E1F1">LazyHGrid</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">rows</span><span style="color: #F6F6F4">: rows, </span><span style="color: #97E1F1">alignment</span><span style="color: #F6F6F4">: .top, </span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">15</span><span style="color: #F6F6F4">) {</span></span>
<span class="line"><span style="color: #F6F6F4">                </span><span style="color: #97E1F1">ForEach</span><span style="color: #F6F6F4">(natureInspiration) { inspiration </span><span style="color: #F286C4">in</span></span>
<span class="line"><span style="color: #F6F6F4">                    </span><span style="color: #97E1F1">InspirationRowView</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">inspiration</span><span style="color: #F6F6F4">: inspiration)</span></span>
<span class="line"><span style="color: #F6F6F4">                        .</span><span style="color: #97E1F1">containerRelativeFrame</span><span style="color: #F6F6F4">(.horizontal,</span></span>
<span class="line"><span style="color: #F6F6F4">                                                 </span><span style="color: #97E1F1">count</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">8</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">                                                 </span><span style="color: #97E1F1">span</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">7</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">                                                 </span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">15</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">                                                 </span><span style="color: #97E1F1">alignment</span><span style="color: #F6F6F4">: .leading)</span></span>
<span class="line"><span style="color: #F6F6F4">                }</span></span>
<span class="line"><span style="color: #F6F6F4">            }</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">            .</span><span style="color: #97E1F1">scrollTargetLayout</span><span style="color: #F6F6F4">(). </span><span style="color: #7B7F8B">// tells the scrollview to use these views for the alignment</span></span>
<span class="line"><span style="color: #F6F6F4">        }</span></span>
<span class="line"><span style="color: #F6F6F4">        .</span><span style="color: #97E1F1">contentMargins</span><span style="color: #F6F6F4">(.horizontal, </span><span style="color: #BF9EEE">20</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">        .</span><span style="color: #97E1F1">scrollBounceBehavior</span><span style="color: #F6F6F4">(.always)</span></span>
<span class="line cbp-line-highlight"><span style="color: #F6F6F4">        .</span><span style="color: #97E1F1">scrollTargetBehavior</span><span style="color: #F6F6F4">(.viewAligned) </span><span style="color: #7B7F8B">// paging behaviour</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<div style="height:21px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph"></p>


<div class="wp-block-image">
<figure class="aligncenter is-resized"><img decoding="async" src="https://www.swiftyplace.com/wp-content/uploads/2023/08/scrollview_paging_introspect.webp" alt="" style="width:658px;height:598px"/></figure>
</div>


<div style="height:41px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">In the above example, I used other new features for ScrollView like customizing its bouncing behavior.</p>



<p class="wp-block-paragraph">You can add a content margin, which is similar to adding padding inside the scrollview:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(1 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="ScrollView(.horizontal) {
   ...
.contentMargins(.horizontal, 20)" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #97E1F1">ScrollView</span><span style="color: #F6F6F4">(.horizontal) {</span></span>
<span class="line"><span style="color: #F6F6F4">   </span><span style="color: #F286C4">...</span></span>
<span class="line"><span style="color: #F6F6F4">.</span><span style="color: #97E1F1">contentMargins</span><span style="color: #F6F6F4">(.horizontal, </span><span style="color: #BF9EEE">20</span><span style="color: #F6F6F4">)</span></span></code></pre></div>



<div style="height:41px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">One of my favorite new features for ScrollView is <code>containerRelativeFrame</code>. In this example, I am using it to make the inspiration view  7 / 8 of the scroll view width. I want to show a little bit of the next column, so that the user understands he can scroll the content:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono-NL.ttf" style="font-size:1rem;font-family:Code-Pro-JetBrains-Mono-NL,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:calc(1 * 0.6 * 1rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="InspirationRowView(inspiration: inspiration)
    .containerRelativeFrame(.horizontal,
                            count: 8,
                            span: 7,
                            spacing: 15,
                            alignment: .leading)" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #97E1F1">InspirationRowView</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1">inspiration</span><span style="color: #F6F6F4">: inspiration)</span></span>
<span class="line"><span style="color: #F6F6F4">    .</span><span style="color: #97E1F1">containerRelativeFrame</span><span style="color: #F6F6F4">(.horizontal,</span></span>
<span class="line"><span style="color: #F6F6F4">                            </span><span style="color: #97E1F1">count</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">8</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">                            </span><span style="color: #97E1F1">span</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">7</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">                            </span><span style="color: #97E1F1">spacing</span><span style="color: #F6F6F4">: </span><span style="color: #BF9EEE">15</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">                            </span><span style="color: #97E1F1">alignment</span><span style="color: #F6F6F4">: .leading)</span></span></code></pre></div>



<div style="height:41px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">We have looked into ScrollViews and how to scroll programmatically, disable scrolling, get the current offset, pin headers, and use Introspect to get paging behavior. ScrollViews are a great way to scroll through your content and keep it organized in sections. With a wide range of options, you can customize the look and feel of your app.</p>



<p class="wp-block-paragraph"><strong>Download the project files from <a href="https://school.swiftyplace.com/17130/files/63e2928f370fa_1675793039_scrollviewproject.zip" target="_blank" rel="noopener">here </a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b07.png" alt="⬇" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong></p>



<p class="wp-block-paragraph"><strong>Further Reading:</strong></p>



<ul class="wp-block-list">
<li><a href="https://www.swiftyplace.com/blog/swiftui-list-view-a-deep-dive-into-one-of-the-most-important-components-of-swiftui" target="_blank" rel="noopener">Compare to SwiftUI List</a></li>



<li>For more complex data with multiple columns check out <a href="https://www.swiftyplace.com/blog/chy7hvne" target="_blank" rel="noopener">Table</a></li>



<li>Learn more about&nbsp;<a href="https://www.swiftyplace.com/blog/mastering-swiftui-image-view" target="_blank" rel="noopener">SwiftUI Image View</a>&nbsp;and how to size images</li>
</ul>
<p>The post <a rel="nofollow" href="http://www.swiftyplace.com/blog/how-to-use-swiftui-scrollview">How to use SwiftUI ScrollView to Create Amazing Collection Views</a> appeared first on <a rel="nofollow" href="http://www.swiftyplace.com">swiftyplace</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.swiftyplace.com/blog/how-to-use-swiftui-scrollview/feed</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: www.swiftyplace.com @ 2026-07-02 13:41:01 by W3 Total Cache
-->