Intrinsic content size is a concept that many developers confuses or, even worse, don't know about. In this tutorial, you learn what intrinsic content size is and how you can use it to your advantage when creating layouts that are powered by Auto Layout.
An Example
Before I explain what intrinsic content size is, I want to illustrate this concept with an example. Fire up Xcode, create a new project, and open the project's main storyboard. Open the Object Library on the right and add a label to the View Controller Scene.
Select the label and center it horizontally and vertically in its superview using the Align menu at the bottom.
With the label selected, open the Attributes Inspector and set the text of the label to Intrinsic Content Size.
As a rule of thumb, every view in the view hierarchy is required to have two constraints per dimension. Even though the label has one constraint for the horizontal dimension and one constraint for the vertical dimension, the resulting layout is satisfiable and unambiguous. Interface Builder doesn't show us any errors or warnings. How is that possible?
The answer, as you may have guessed, is the label's intrinsic content size. Even though you can add explicit constraints to a view to define its width and height, some views already know what size they should be. And that is a good thing.
The label we added to the View Controller Scene illustrates this well. You could fix the size of the label and that is sometimes exactly what you want. Most of the times, however, you want the size of the label to change depending on its contents, that is, the text it is displaying.
Fortunately, labels already know what their size should be. That is the intrinsic content size of the label. The intrinsic content size is dynamic and calculated at runtime. That is what makes it such a powerful concept.
If the font of the label changes, for example, the intrinsic content size of the label also changes. The same happens when the text of the label changes or when the user increases the font size system-wide in the accessibility settings of the operating system.
How Does It Work
For this discussion, you need to know that there are two types of constraints, implicit constraints and explicit constraints. Explicit constraints are the constraints you create ... well ... explicitly. You can add constraints in code or in Interface Builder. Implicit constraints are constraints Auto Layout creates for you.
Auto Layout translates the intrinsic content size of a view to a set of implicit constraints, one constraint per dimension. In the above example, Auto Layout adds a horizontal and a vertical constraint to the label based on the intrinsic content size of the label.
It is important to know that not every view has an intrinsic content size. A vanilla UIView
instance, for example, does not have an intrinsic content size. This means that you need to add four explicit constraints to describe the size and position of a UIView
instance in a user interface.
Conflicts & Intrinsic Content Size
By now, it should be clear that intrinsic content size greatly simplifies working with Auto Layout. The fewer explicit constraints you need to add, the more flexible and dynamic the resulting layout is.
But you may be wondering what happens if the intrinsic content size of several views cause a conflict. This is a likely scenario. Let me show you what that looks like in practice.
Revisit the main storyboard and remove the label we added earlier. Add two labels at the top of the view controller's view. Pin one label to the top left of its superview and pin one label to the top right of its superview. Finally, add an explicit constraint that fixes the space of the left label's trailing edge to the right label's leading edge to 8.0 points.
Each label knows exactly what size it should be, but that is causing a conflict. The conflict is resolved if we remove the constraint that fixes the spacing between the labels. But that isn't the result we are after. We currently have an unsatisfiable layout.
Content Hugging
To better understand what the problem is, we need to inspect the error message. You can view the errors by opening the Document Outline and clicking the red arrow at the top right. The errors say something about content hugging and compression resistance. What is that about?
The intrinsic content size of a label is equal to the size of the label's text. In this example, however, we force the labels to be wider than their intrinsic content size. That is fine, though. The layout engine can fix the layout by stretching one of the labels beyond their intrinsic content size width.
The question is "Which label should the layout engine stretch?" To answer this question, the layout engine inspects the horizontal content hugging priority of each label. Let me explain how that works.
Every view has a content hugging priority for each dimension. It determines how eager a view is to grow beyond its intrinsic content size. These priorities are taken into account when the layout engine inspects the constraints of the user interface. In fact, at runtime, the content hugging priorities are translated into constraints, which makes the job of the layout engine much easier.
The content hugging priority determines how eager a view is to grow beyond its intrinsic content size.
Select the left label and open the Size Inspector. At the bottom you can see the Content Hugging Priority, one for the horizontal dimension and one for the vertical dimension. The default values for labels are 251. Lower the horizontal content hugging priority of the left label to 250 and see how the user interface changes.
To see the result we need to update the frames. Click the Resolve Auto Layout Issues menu at the bottom and choose Update Frames.
Because we lowered the content hugging priority of the left label, it is now less reluctant to grow horizontally in size than the right label. As a result, to satisfy the layout, the layout engine stretches the left label. The size of the right label is equal to that of its intrinsic content size, which is determined by its contents.
Content Compression Resistance
Below the content hugging priorities, you can see the content compression resistance priorities of the label. These values determine how easy it is to compress the label if it needs to shrink.
The content compression resistance priority determine how easy it is to compress the label if it needs to shrink.
To see how this works, we need to add more text to the labels than they can fit. The result is a lot of red and a few Auto Layout errors.
The layout engine is having another problem. It needs to shrink one of the labels. One of the labels needs to be less wide than its intrinsic content size. At the moment, both labels have identical content compression resistance priorities and that is causing a conflict. The layout engine cannot choose which label should shrink.
Select the left label and set its horizontal content compression resistance to 749. After updating the frames, everything looks fine again. By lowering the horizontal content compression resistance of the left label, the layout engine has decided to decrease the width of the left label to make sure the right label can show its contents.
What's Next?
Intrinsic content size, content hugging and content compression resistance are important aspects of Auto Layout. They are fundamental to understand Auto Layout.
Questions? Leave them in the comments below or reach out to me on Twitter.