# Working with percentages in SwiftUI layout

DevFeed: [Working with percentages in SwiftUI layout](<https://devfeed.tech/articles/working-with-percentages-in-swiftui-layout-21723.md>)

Original publisher: [Read original article](<https://oleb.net/2023/swiftui-relative-size/>)

Author: Ole Begemann

Published: 2023-03-23T22:31:11Z

Content type: tutorial

Language: en

Sources: [Ole Begemann](<https://devfeed.tech/sources/ole-begemann.md>)

Topics: [SwiftUI](<https://devfeed.tech/topics/swiftui.md>), [Code](<https://devfeed.tech/topics/code.md>)

Tags: [build](<https://devfeed.tech/tags/build.md>), [code](<https://devfeed.tech/tags/code.md>), [layout](<https://devfeed.tech/tags/layout.md>), [swiftui](<https://devfeed.tech/tags/swiftui.md>)

## AI overview

A tutorial on implementing relative sizing in SwiftUI by creating a custom Layout-based modifier. The modifier scales the proposed width and height before passing them to a single subview, with examples using chat bubbles and maximum-width constraints.

## Source excerpt

SwiftUI's layout primitives generally don't provide relative sizing options, e.g. "make this view 50 % of the width of its container". Let's build our own! Use case: chat bubbles Consider this chat conversation view as an example of what I want to build. The chat bubbles always remain 80 % as wide as their container as the view is resized: The chat bubbles should become 80 % as wide as their container. Download video Building a proportional sizing modifier 1. The Layout We can build our own relative sizing modifier on top of the Layout protocol. The layout multiplies its own proposed size (which it receives from its parent view) with the given factors for width and height. It then proposes this modified size to its only subview. Here's the implementation (the full code, including the demo app, is on GitHub): /// A custom layout that proposes a percentage of its /// received proposed size to its subview. /// /// - Precondition: must contain exactly one subview. fileprivate struct RelativeSizeLayout: Layout { var relativeWidth: Double var relativeHeight: Double func sizeThatFits( proposal: ProposedViewSize, subviews: Subviews, cache: inout () ) -> CGSize { assert(subviews.count == 1, "expects a single subview") let resizedProposal = ProposedViewSize( width: proposal.width.map { $0 * relativeWidth }, height: proposal.height.map { $0 * relativeHeight } ) return subviews[0].sizeThatFits(resizedProposal) } func placeSubviews( in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout () ) { assert(subviews.count == 1, "expects a single subview") let resizedProposal = ProposedViewSize( width: proposal.width.map { $0 * relativeWidth }, height: proposal.height.map { $0 * relativeHeight } ) subviews[0].place( at: CGPoint(x: bounds.midX, y: bounds.midY), anchor: .center, proposal: resizedProposal ) } } Notes: I made the type private because I want to control how it can be used. This is important for maintaining the assumption that the layout only ever has