Blog Post

An In-Depth Look at Blur Effect Materials on iOS

Illustration: An In-Depth Look at Blur Effect Materials on iOS

iOS offers a collection of neatly designed UI elements in UIKit, which a developer can then use to create a catchy-looking UI.

In this blog post, we’ll discuss the elements that provide blur effects, or materials, as defined in the Human Interface Guidelines. These elements are used by apps and iOS alike.

The first example where this can be seen in action, and perhaps the one most viewed by users, is that of notification banners. The blur effects used on notification banners help them stand out when compared to their surrounding elements, thereby pointing the user to important content they should interact with. But we also see blur effects used in app folders on the Home screen and even in Notification Center widgets.

Using Blur Effects

Blur effects can be added using the UIVisualEffectView API. To do this, create a UIVisualEffectView and add it to the view hierarchy over the background content. The content needs to be added as a subview of the contentView of the initially added UIVisualEffectView element. The most important part of this is to set the effect of the visual effect view element. There are two options: UIBlurEffect and UIVibrancyEffect.

UIBlurEffect adds a blur over the content underneath the visual effect view and has been around since iOS 8. Meanwhile, UIVibrancyEffect makes the content under the visual effect view more prominent. This has also been available since iOS 8. However, Apple mentioned in the documentation for UIVibrancyEffect that the effect is meant to be used as a subeffect by adding it in the contentView of a visual effect view with a UIBlurEffect to make the actual contents appear vivid. We will get to the characteristics of these effects after our code sample below.

Adding a Blur Effect

To add a blur effect, do the following:

// Add the `UIVisualEffectView` to the view hierarchy.
let visualEffectView = UIVisualEffectView(effect: nil)
visualEffectView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(visualEffectView)
// Add appropriate constraints for the `visualEffectView`.

// Add your content to the visual effect view.
let contentView = makeMyFancyPrimaryContentView()
visualEffectView.contentView.addSubview(contentView)
// Add constraints for your `contentView`.

// Finally, set the appropriate blur effect for the visual effect view.
visualEffectView.effect = UIBlurEffect(style: .systemMaterial)
// Add the `UIVisualEffectView` to the view hierarchy.
UIVisualEffectView *visualEffectView = [[UIVisualEffectView alloc] initWithEffect:nil];
visualEffectView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:visualEffectView];
// Add appropriate constraints for the `visualEffectView`.

// Add your content to the visual effect view.
UIView *contentView = [self makeMyFancyPrimaryContentView];
[visualEffectView.contentView addSubview:contentView];
// Add constraints for your `contentView`.

// Finally, set the appropriate blur effect for the visual effect view.
visualEffectView.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleSystemMaterial];

Adding a Vibrancy Effect

To add a vibrancy effect, do the following:

// A vibrancy effect needs an underlying blur effect.
// Add the initial `UIVisualEffectView` to the view hierarchy.
let blurEffectView = UIVisualEffectView(effect: nil)
blurEffectView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(blurEffectView)
// Add appropriate constraints for the `blurEffectView`.

// Create your desired blur effect.
let blurEffect = UIBlurEffect(style: .systemMaterial)

// Set the created blur effect for the visual effect view.
blurEffectView.effect = blurEffect

// Create a `UIVibrancyEffect` using the above created blur effect.
let vibrancyEffect = UIVibrancyEffect(blurEffect: blurEffect, style: .fill)

// Add a new `UIVibrancyEffectView` to the `contentView` of the earlier added `UIVisualEffectView`.
let vibrancyEffectView = UIVisualEffectView(effect: vibrancyEffect)
vibrancyEffectView.translatesAutoresizingMaskIntoConstraints = false
blurEffectView.contentView.addSubview(vibrancyEffectView)
// Add appropriate constraints for the `vibrancyEffectView`.

// Add the content that should be made more vibrant.
let contentView = makeMyFancyPrimaryContentView()
vibrancyEffectView.contentView.addSubview(contentView)
// Add constraints for your `contentView`.
// A vibrancy effect needs an underlying blur effect.
// Add the initial `UIVisualEffectView` to the view hierarchy.
UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:nil];
blurEffectView.translatesAutoresizingMaskIntoConstraints = NO;
[view addSubview:blurEffectView];
// Add appropriate constraints for the `visualEffectView`.

// Create your desired blur effect.
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleSystemMaterial];

// Set the created blur effect for the visual effect view.
blurEffectView.effect = blurEffect;

// Create a `UIVibrancyEffect` using the above created blur effect.
UIVibrancyEffect *vibrancyEffect = [UIVibrancyEffect effectForBlurEffect:blurEffect style:UIVibrancyEffectStyleFill];

// Add a new `UIVibrancyEffectView` to the `contentView` of the earlier added `UIVisualEffectView`.
UIVisualEffectView *vibrancyEffectView = [[UIVisualEffectView alloc] initWithEffect:vibrancyEffect];
vibrancyEffectView.translatesAutoresizingMaskIntoConstraints = NO;
[blurEffectView.contentView addSubview:vibrancyEffectView];
// Add appropriate constraints for the `vibrancyEffectView`.

// Add the content that should be made more vibrant.
UIView *contentView = [self makeMyFancyPrimaryContentView];
[vibrancyEffectView.contentView addSubview:contentView];
// Add constraints for your `contentView`.

Blur Effect Styles

In iOS 13, we saw the introduction of Dark Mode. However, some of the effect styles that were available before iOS 13 are not dynamic, making them appear the same (light) in Dark Mode. As a result, they are not particularly useful when both modes need to be supported, as the styling won’t match the surrounding views.

Fortunately, UIBlurEffectStyle has new styles that came out with iOS 13 which change with the system appearance. These new styles not only update a blur effect based on the selected UI mode (dark/light), but they also have a new blur effect that is more in line with styles used in the system UI. Additionally, there are standalone styles that provide the same blur effect, but they will always be light/dark regardless of the selected user interface mode.

Adaptable Modern Effects Light Dark
.systemUltraThinMaterial: Adds an ultra-thin blur effect between the underlying background and foreground content. Works with light and dark appearances. Available from iOS 13 onward (not available on watchOS and tvOS yet).
.systemUltraThinMaterialLight: Same as .systemUltraThinMaterial, but the effect is always light (even with dark appearance).
.systemUltraThinMaterialDark: Same as .systemUltraThinMaterial, but the effect is always dark (even with light appearance).
Light appearance image for systemUltraThinMaterial Dark Mode image for systemUltraThinMaterial
.systemThinMaterial: Adds a thin blur effect between the underlying background and foreground content. Works with light and dark appearances.
.systemThinMaterialLight: Same as .systemThinMaterial, but the effect is always light (even with dark appearance).
.systemThinMaterialDark: Same as .systemThinMaterial, but the effect is always dark (even with light appearance).
Light Mode image for systemThinMaterial Dark Mode image for systemThinMaterial
.systemMaterial: Adds a blur effect with a normal thickness that’s the same as the default system thickness. Works with light and dark appearances.
.systemMaterialLight: Same as .systemMaterial, but the effect is always light (even with dark appearance).
.systemThinMaterialDark: Same as .systemThinMaterial, but the effect is always dark (even with light appearance).
Light Mode image for systemMaterial Dark Mode image for systemMaterial
.systemThickMaterial: Adds a blur effect thicker than the normal thickness. Works with light and dark appearances.
.systemThickMaterialLight: Same as .systemThickMaterial, but the effect is always light (even with dark appearance).
.systemThickMaterialDark: Same as .systemThickMaterial, but the effect is always dark (even with light appearance).
Light Mode image for systemThickMaterial Dark Mode image for systemThickMaterial
.systemChromeMaterial: Adds a blur effect resembling the system’s chrome. Works with light and dark appearances.
.systemChromeMaterialLight: Same as .systemChromeMaterial, but the effect is always light (even with dark appearance).
.systemChromeMaterialDark: Same as .systemChromeMaterial, but the effect is always dark (even with light appearance).
Light Mode image for systemChromeMaterial Dark Mode image for systemUltraThinMaterial

The background image used in the screenshots is by Massimiliano Morosinotto on Unsplash.

Below is the list of the traditional blur effect styles. We are not attaching screenshots for them since they have been around for a few years now, and also because using the modern effects is the correct way forward.

Blur Effect Style Description
.extraLight This has a lighter hue than the underlying background content. It does not adapt to Dark Mode. Available from iOS 10 onward.
.light This has a hue area approximately the same as the underlying background content. It does not adapt to Dark Mode. Available from iOS 10 onward.
.dark This has a darker hue than the underlying background content. It does not adapt to Dark Mode. Available from iOS 10 onward.
.extraDark This is darker compared to the effect with .dark. It does not adapt to Dark Mode. Available from iOS 10 onward.
.regular This uses the .light effect with light appearance and the .dark effect with dark appearance.
.prominent This uses the .extraLight for light mode, .dark on iOS, and .extraDark on tvOS for Dark Mode. Available from iOS 10 onward.

Vibrancy Effect Styles

UIVibrancyEffectStyle has styles for labels based on the type of the content (primary, secondary, tertiary, quaternary). For larger views having multiple subviews, it has fill effect styles, again based on the type of the content shown in it (primary, secondary, tertiary).

Vibrancy Effect Style Description
.label Used for effects containing labels that have primary content.
.secondaryLabel Used for effects containing labels that have secondary content.
.tertiaryLabel Used for effects containing labels that have tertiary content.
.quaternaryLabel Used for effects containing labels that have quaternary content.
.fill Used for effects containing larger areas filled with primary content.
.secondaryFill Used for effects containing larger areas filled with secondary content.
.tertiaryFill Used for effects containing larger areas filled with tertiary content.
.separator Used for effects containing separator lines.

All the above vibrancy effects are compatible with light and dark appearances and available only from iOS 13 onward.

Blur Effect Vibrant Effect
Image of a label on a blur effect Image of a label on a vibrancy effect

The content of the blur effect in the second screenshot has a lower contrast. A .secondaryLabel vibrancy effect is added on top of the blur effect, which is the same as the blur effect from the first screenshot. This is because the content has to match the system’s secondary content style.

Challenges of Picking the Appropriate Effect Style

Consider the case of overlaid bars, such as the scrubber bar at the bottom and the tab bar at the top in the PSPDFViewController. The rendered PDF page can extend underneath these bars, and so the effect style had to be chosen carefully to ensure the visibility of the contents of the overlaid bars.

If you look at the screenshots below, the one on the left side uses .systemThinMaterial. We decided not to use this, since it allows the content underneath it to pass through, thereby decreasing the visibility of the text in the tab bars.

For our SDK, we need to have a universal solution that can work with any kind of content rendered underneath. Blurs look snazzy in a design, but it is easy to end up with poor legibility. Meanwhile, using thicker materials is safer in terms of the legibility of content. Since we were already using the thicker system material (.systemThickMaterial) for the navigation and scrubber bars, we had to ensure that the selected tab bar was distinguishable from the other bars and also from the navigation bar above. So we decided to go with the style similar to the system (.systemMaterial) to ensure legibility of the content underneath.

Rejected Effect Material Shipped Effect Material
Image of a rejected effect material Image of the shipped effect material

This can be seen in the above screenshots. The rejected blur effect is applied to the tab bar, which is not selected, and as a result, it almost blends into the navigation bar above.

Conclusion

In this post, we discussed the different blur effects and blur effect styles available on iOS. We also gave examples of how to use them and shared some challenges we encountered in picking the appropriate effect.

There are no hard and fast rules as to which blur effect style should be picked. If your effect is added over static content, then you can simply cycle through the styles and pick the one that suits you best.

When it comes to adding a blur effect over dynamic content, it can take more than a few tries to get it right. However, it is well worth the time to pick the correct effect and effect style to not only get a great look but also ensure legibility.

Share Post
Free 60-Day Trial Try PSPDFKit in your app today.
Free Trial

Related Articles

Explore more
PRODUCTS  |  iOS • Releases

PSPDFKit 13.4 for iOS Introduces Revamped API Documentation and Improves Multiple Annotation Selection

DEVELOPMENT  |  visionOS • iOS

Apple’s Vision of Our Digital Future

PRODUCTS  |  iOS • visionOS • Mac Catalyst • Releases

PSPDFKit 13.3 for iOS Adds Long-Term Validation for Digital Signatures