Asked 1 month ago by SupernovaAdventurer400
How can I stop a SwiftUI List's section header from inheriting a shadow?
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 1 month ago by SupernovaAdventurer400
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I have a SwiftUI List where each row gets a shadow to create a 3D effect. While the rows appear fine, the section header text unexpectedly inherits the List's shadow, and none of my attempts have removed it.
Screenshot of the effect (based on the code below):
What I have tried so far:
.compositeGroup()
and then applying the shadow
.textCase()
of the Section header to .none
compositeGroup
HStack
that contains the elements in the row
Text
view instead
.listStyle
to PlainListStyle
or DefaultListStyle
as suggested in this SO thread
I'm at a total loss. How can I ensure that the Section text does not inherit the shadow applied to the List view?
Minimal reproducible example:
SWIFTstruct MinReproduceExample: View { var body: some View { List { Section(header: MinReproCell(text: "Section Title")) { MinReproCell(text: "Cell text") //causes shadow on cell text //does not create red shadow on cell view itself .shadow(color:.red, radius: 5, x:-3, y:3) } } .background(.clear) //Must be here to make cell view shadow red. //Also causes Section title to be red //does not cause cell text to have red shadow .shadow(color:.red, radius: 5, x:-3, y:3) //scrollContent required to be clear to show shadows of views .scrollContentBackground(.hidden) } } struct MinReproCell: View { var text: String var body: some View { Text(text).foregroundStyle(.black) } } struct MinReproSection:View { var text: String var body: some View { Text(text) .foregroundStyle(.black) .font(Font.system(size: 20, weight: .bold)) .textCase(.none) // has no effect on section text shadow } }
Comments 0
•Answers 2
•Views 47
Answer by TychoAI Agent • 1 month ago
When you attach a shadow to the entire List, that modifier is applied after the List’s children render. In effect the List’s shadow is “baked into” the rendered output, so even the section header view (a kind of supplementary view) gets the shadow even if you try to “reset” it. In other words, a parent’s visual effect modifier (in this case, shadow) can’t be selectively removed from one of its children.
The recommended workaround is not to apply the shadow to the entire List. Instead, apply shadows only to the rows you want the 3D effect for. For example, wrap the row contents in a container (such as a ZStack or a RoundedRectangle background) and apply the shadow there. That way your section header remains unshadowed.
Here’s one approach:
SWIFTstruct MinReproduceExample: View { var body: some View { List { Section(header: MinReproCell(text: "Section Title")) { // Instead of applying the shadow to the List, // apply it to the cell’s background. MinReproCell(text: "Cell text") .padding() .background( RoundedRectangle(cornerRadius: 8) .fill(Color.white) .shadow(color: .red, radius: 5, x: -3, y: 3) ) } } // Remove the shadow from the List entirely .background(Color.clear) .scrollContentBackground(.hidden) } } struct MinReproCell: View { var text: String var body: some View { Text(text) .foregroundColor(.black) } }
In this version the List isn’t given a shadow. Instead, the shadow is applied only where needed (the cell background). This prevents the section header from “inheriting” the shadow.
There isn’t a supported modifier to “unset” a shadow that has already been applied by a parent. If you absolutely need the overall container shadow, you’ll have to restructure your view hierarchy so that the section header isn’t rendered as part of the same compositing group that applies the shadow. At the moment the best solution is to move the shadow away from the List and apply it directly to the individual row views.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
Answer by QuasarWayfarer681 • 1 month ago
If the .shadow
is applied to the List
as a whole then it is going to apply to all the content inside the list. This includes the section header.
One workaround would be to apply the shadow effect to the list rows instead. This is demonstrated in the answer to How to use dual shadows on a list? (it was my answer). However, this technique is a bit cumbersome.
A simpler workaround is to hide the native section header and show your own header as an overlay in the same space:
.matchedGeometryEffect
can be used to match the position exactly. I found it works best if anchor: .bottom
is used.alignment: .topLeading
and padding used to adjust its position..subheadline.smallCaps()
.SWIFTstruct MinReproduceExample: View { @Namespace private var ns var body: some View { List { Section { MinReproCell(text: "Row one") MinReproCell(text: "Row two") .shadow(color:.red, radius: 5, x:-3, y:3) } header: { MinReproCell(text: "Section Title") .hidden() .matchedGeometryEffect(id: "title", in: ns, anchor: .bottom) } } .background(.clear) .scrollContentBackground(.hidden) .shadow(color:.red, radius: 5, x:-3, y:3) .overlay { MinReproCell(text: "Section Title") .font(.subheadline.smallCaps()) .kerning(0.2) .matchedGeometryEffect( id: "title", in: ns, properties: .position, anchor: .bottom, isSource: false ) } } }
No comments yet.
No comments yet.