Shadow (skugga) — en visuell effekt i mobila gränssnitt som skapar illusionen av djup och hierarki mellan element. Skuggor visar vilket element som är högre i Z-planet och därför är viktigare eller interaktivt. Enligt Material Design Guidelines (Google, 2026) använder systemets skuggor fem viktiga höjder (elevation): 0 dp (platt), 1–4 dp (knappar), 6–12 dp (kort), 16–24 dp (dialoger), 24+ dp (modala fönster). Läs mer om höjden på element i artikeln om Elevation.
Huvudpunkter
Skugga (shadow) i användargränssnitt — en visuell effekt som efterliknar belysning och djup. En skugga skapas genom att rita en mörk suddig kopia av elementet som är förskjuten i förhållande till originalet. I mobil design har skuggor tre funktioner: visar hierarki (högre element — längre skugga), signalerar interaktivitet (knappar med skugga ser klickbara ut), separerar innehåll från bakgrund (kort med skugga uppfattas som separata block).
I Googles Material Design är skuggor oupplösligt kopplade till konceptet elevation (höjd). Varje element upptar en viss höjd i Z-koordinaten och skuggan är en projektion av belysning uppifrån. Apples Human Interface Guidelines föreskriver inget strikt höjdsystem men rekommenderar att använda skuggor för att skapa visuell hierarki och djup i gränssnitt.
Enligt forskning från Nielsen Norman Group (2024) minskar korrekt placerade skuggor tiden för att hitta ett interaktivt element med 24%. Skuggor hjälper också användare med synnedsättning att urskilja elementens gränser. Alltför många skuggor (3+ nivåer på en skärm) ökar dock den kognitiva belastningen och försämrar uppfattningen.
På iOS implementeras skuggor via CALayers egenskaper: shadowColor anger skuggans färg, shadowOffset — förskjutningen i CGSize (x, y), shadowRadius — oskärpans radie, shadowOpacity — opaciteten från 0 till 1. För prestanda rekommenderas också att ställa in shadowPath — UIBezierPath som beskriver skuggans form, så att Core Animation inte beräknar den automatiskt.
// UIKit: konfigurera skugga via CALayer
import UIKit
let cardView = UIView()
cardView.backgroundColor = .systemBackground
cardView.layer.cornerRadius = 12
// Konfigurera skugga
cardView.layer.shadowColor = UIColor.black.cgColor
cardView.layer.shadowOpacity = 0.15
cardView.layer.shadowOffset = CGSize(width: 0, height: 4)
cardView.layer.shadowRadius = 8
"> Optimering: explicit shadowPath
cardView.layer.shadowPath = UIBezierPath(
roundedRect: cardView.bounds,
cornerRadius: 12
).cgPath
I SwiftUI ställs skuggor in via modifieraren .shadow() med parametrarna color, radius, x, y. SwiftUI tillämpar automatiskt shadowPath och hanterar renderingsprestandan. För avancerade skuggor (inre skuggor, flera skuggor) använd overlay() med LinearGradient.
// SwiftUI: skugga via shadow-modifieraren
import SwiftUI
VStack {
Text("Kort med skugga")
.padding()
.background(Color.white)
.cornerRadius(16)
.shadow(
color: .black.opacity(0.15),
radius: 10,
x: 0,
y: 4
)
}
Prestanda för skuggor på iOS: om shadowPath inte är inställt beräknar Core Animation skuggan baserat på lagrets form i varje bildruta, vilket kan orsaka fördröjningar under animering. För statiska element, ställ alltid in shadowPath. För animerade element, använd shouldRasterize = true på CALayer för att cachelagra skuggan i ett separat lager. I SwiftUI hanteras rastrering via .drawingGroup().
I Android implementeras skuggor i Material Design via elevation — egenskapen för View som anger elementets höjd i Z-koordinaten. Systemet ritar automatiskt en skugga baserat på elevation och outlineProvider (elementets kontur). Ju högre elevation, desto större och suddigare skugga. För Views som inte ärver Material Design (t.ex. AppCompat) fungerar skuggor endast med hårdvaruacceleration aktiverad.
<!-- XML: elevation via attribut -->
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="12dp"
app:cardElevation="6dp">
<!-- Kortets innehåll -->
</androidx.cardview.widget.CardView>
För anpassade skuggor i Android View System används OutlineProvider. ViewOutlineProvider gör det möjligt att ställa in en godtycklig form via outline.setRoundRect() eller outline.setPath(). Utan OutlineProvider ritas skuggan baserat på View:ens rektangulära form, vilket inte tar hänsyn till rundade hörn.
// Kotlin: anpassad OutlineProvider för skugga
import android.graphics.Outline
import android.view.View
import android.view.ViewOutlineProvider
val myView: View = findViewById(R.id.myView)
myView.outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
outline.setRoundRect(
0, 0, view.width, view.height,
12f // hörnradie
)
}
}
myView.elevation = 8f // skugghöjd i px
myView.translationZ = 4f // extra höjd vid tryckning
I Jetpack Compose hanteras skuggor via Modifier.shadow() och elevation i komponenterna Card och Surface. Modifier.shadow() accepterar elevation och shape. Till skillnad från View System ritar Compose skuggor i sin egen renderingspipeline, vilket ger mer förutsägbart beteende på alla Android-versioner.
// Jetpack Compose: skugga via Modifier.shadow
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
Card(
modifier = Modifier.shadow(
elevation = 6.dp,
shape = RoundedCornerShape(12.dp),
clip = false
),
colors = CardDefaults.cardColors(containerColor = Color.White)
) {
Text("Card med anpassad skugga")
}
Korrekt användning av skuggor förbättrar gränssnittsuppfattningen, felaktig användning — skapar visuellt brus och försämrar prestanda. Material Design definierar fem nivåer av elevation: 0 dp (ingen skugga), 1–4 dp (knappar, chips), 6–12 dp (kort, menyer), 16–24 dp (dialoger, bottenpaneler), 24+ dp (modala fönster, FAB).
| Nivå | Elevation | Element | Skuggans egenskap |
|---|---|---|---|
| 0 | 0 dp | Text, ikoner, bakgrund | Ingen skugga, platt lager |
| 1 | 1–4 dp | Knappar, inmatningsfält | Lätt skugga, liten förskjutning |
| 2 | 6–12 dp | Kort, Snackbar | Måttlig skugga, märkbar oskärpa |
| 3 | 16–24 dp | Dialoger, menyer | Djup skugga, stor oskärpa |
| 4 | 24+ dp | Modala fönster | Maximal skugga, elementet svävar |
Regler för god praxis: (1) använd inte skuggor för element som inte bör dra uppmärksamhet (bakgrunder, avskiljare), (2) skuggans höjd bör motsvara elementets betydelse — ju viktigare, desto högre, (3) vid knapptryckning minska elevation animerat för taktil återkoppling, (4) undvik skuggor på mörka bakgrunder — använd overlay (ljusare/mörkare) istället för skugga. I Material You (Android 12+) anpassar sig skuggor till temat: på mörk bakgrund ersätts elevation med ett färglager (surface tint).
I Flutter implementeras skuggor via BoxShadow inuti BoxDecoration. BoxShadow accepterar color, offset, blurRadius och spreadRadius. Flutter stöder flera skuggor: att skicka en lista med BoxShadow gör det möjligt att skapa komplexa effekter — till exempel yttre skugga + inre belysning. PhysicalModel — ett alternativ som simulerar en fysisk skugga baserat på form (BeveledRectangleBorder, CircleBorder).
// Flutter: skugga via BoxDecoration + BoxShadow
import 'package:flutter/material.dart';
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.0),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.15),
offset: Offset(0, 4),
blurRadius: 8.0,
spreadRadius: 0,
),
],
),
child: Text('Container med skugga'),
)
// PhysicalModel för fysisk skugga
PhysicalModel(
color: Colors.white,
elevation: 6.0,
shadowColor: Colors.black.withOpacity(0.2),
borderRadius: BorderRadius.circular(12.0),
child: Text('Fysisk modell med skugga'),
)
Prestanda: BoxShadow med flera skuggor kan orsaka omritning (repaint) vid varje förändring. För statiska element, använd PhysicalModel — det cachelagrar skuggan i ett separat lager (RepaintBoundary). I Flutter 3.16+ har stöd för Material 3 elevation lagts till med adaptiva skuggor som ändrar färg och oskärpa beroende på tema (ljust/mörkt).
Vanliga frågor
Elevation — är den numeriska höjden av elementet i Z-koordinaten, medan shadow (skugga) — den visuella effekten som skapas av denna höjd. I Android är elevation en egenskap hos View som automatiskt genererar en skugga. Inom design används elevation och shadow ofta som utbytbara termer, men tekniskt sett är elevation orsaken och shadow är resultatet.
Kontrollera: (1) har View elevation större än 0, (2) är outlineProvider inställt (om View inte är från Material-biblioteket), (3) är hårdvaruacceleration aktiverad (android:hardwareAccelerated="true" i manifestet). CardView hanterar outlineProvider automatiskt. För anpassade Views, anropa view.outlineProvider = ViewOutlineProvider.BACKGROUND.
CALayer stöder inte inre skuggor direkt. Använd en kombination: CAGradientLayer med svart färg och genomskinlighet inuti masken (mask), eller placera en UIImageView med en raster inre skugga. I SwiftUI implementeras inre skugga via overlay med LinearGradient och blendMode(.multiply).
I Android, använd translationZ för animering: i viloläge elevation = 2 dp, vid tryckning translationZ = 4 dp (total höjd 6 dp). På iOS, animera shadowOffset och shadowRadius samtidigt med knappens transformation. I SwiftUI, använd withAnimation med ändring av elevation via Modifier.shadow(). I Flutter — AnimatedContainer med ändring av BoxShadow.
Material Design rekommenderar inte mer än tre nivåer av elevation på en skärm. Om det finns fler element med skugga — gruppera dem i grupper med samma höjd. Ett överdrivet antal skuggor skapar visuellt brus och minskar renderingsprestandan på enheter i mellan- och budgetsegmentet.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också