I have a couple UIButtons, and in IB they're set to Aspect Fit, but for some reason they're always stretching. Is there something else you have to set? I tried all the different view modes and none of them work, they all stretch.
-
@Werner Altesischer's answer is the right one. Make the appropriate changes. – Harshit Gupta Jan 19 '14 at 21:01
-
1@marty Are you setting background image or image? background image does not support it, only image. – Juan Boero Aug 17 '15 at 22:25
21 Answers
The solution is to set the contentMode
on the imageView
property of the UIButton
. The UIButton
has to be created with custom type for this to work I believe (otherwise nil
is returned for this property).

- 9,564
- 146
- 81
- 122

- 10,080
- 4
- 53
- 60
-
71This worked for me: `[button.imageView setContentMode:UIViewContentModeScaleAspectFit];` – ayreguitar Sep 08 '11 at 09:04
-
2This works for me also but if I set adjustsImageWhenHighlighted=YES, the image is stretched again when I tap on the button. – cduck Feb 01 '12 at 00:06
-
Set adjustImageWhenHighlighted to NO and supply an image yourself for the highlighted state instead – Werner Altewischer Feb 28 '12 at 15:20
-
1
-
3In iOS 8, this actually doesn't work for me. The original answer (with placing an imageView behind a transparent button) works best. – user1416564 Sep 30 '15 at 12:57
-
in SWIFT: `button.imageView.contentMode = UIViewContentMode.ScaleAspectFit` – drpawelo Mar 23 '16 at 12:49
-
7in Swift du jour: `button.imageView!.contentMode = UIViewContentMode.scaleAspectFit` – Nestor Sep 01 '17 at 09:26
-
1Is this possible within the storyboard designer, or must it be set in code? – Damn Vegetables Oct 21 '17 at 17:09
-
Also, on iOS 11+, the content mode has to be set before the image. Otherwise it will only get its good shape after taping on it. – Tulleb Apr 16 '19 at 13:53
-
What might cause an image set as the image for a button to appear cut off? Text appears fine if put instead of image – Jun 17 '19 at 02:29
This method worked for me very well.:
In Xib select the button and set user defined runtime attributes
:
- Key path:
self.imageView.contentMode
- Type:
Number
- Value:
1
We use number because you cant use enum there. But the UIViewContentModeScaleAspectFit is equal to 1.

- 3,728
- 3
- 37
- 60

- 639
- 5
- 4
-
2This also updated the image in the interface builder during design time. Great solution. – George Filippakos May 19 '17 at 21:38
-
Great solution, few code and works like a charm , the enum is based on content mode list items. – Kross Sep 26 '17 at 18:51
-
You can also add an extension to make it a bit easier: `extension UIButton { @IBInspectable var imageContentMode: Int { get {return imageView?.contentMode.rawValue ?? 0} set {imageView?.contentMode = UIViewContentMode(rawValue: newValue) ?? .scaleAspectFit} } }` – Yonat Dec 12 '17 at 07:10
-
I've had that problem before. I solved it by putting my image in a UIImageView
, where contentMode
settings actually work, and putting a transparent custom UIButton
over top of that.
EDIT: This answer is obsolete. See @Werner Altewischer's answer for the correct answer in modern versions of iOS.
-
-
How do you manage button states with this technique? Seems like responding to user interaction like "highlighted" would be a nightmare. – SooDesuNe Oct 24 '12 at 02:30
-
3This might have been the right way to do this 2.5 years ago when this question was answered, but now you can edit the UIButton's internal ImageView and set the the content mode there. See the answer by @Werner Altewischer – Steve Haley Apr 05 '13 at 11:56
If you are doing this in Interface Builder, you can use the Runtime attributes inspector to set this directly without any code.
Set your Key Path on the button to be "imageView.contentMode" with a type of "Number" and a value of "1" (or whichever mode you would like).

- 5,717
- 2
- 35
- 35
Use button's imageView for contentMode. Not directly on the button itself.
homeButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
homeButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
homeButton.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
[homeButton setImage:[UIImage imageNamed:kPNGLogo] forState:UIControlStateNormal];

- 1,001
- 1
- 8
- 17
I had this problem a while back. The issue I had was i was trying to apply this effect to the background UIButton which is limited and therefore means you cannot adjust it as easy.
The trick is to set it as just an image then apply @ayreguitar's technique and that should fix it!
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setContentMode:UIViewContentModeScaleAspectFill];
[myButton setImage:@"myImage.png" forState:UIControlStateNormal];

- 842
- 9
- 14
If you put the image in an UIImageView
behind the button, you'll loose the built-in functionality of the UIButton
class, such as adjustsImageWhenHighlighted
and adjustsImageWhenDisabled
, and of course the ability to set different images for different states (without the hazzle of doing this yourself).
If we want to have an image unstreched for all control states, one approuch is to get the image using imageWithCGImage:scale:orientation
, as in the following method:
- (UIImage *) getScaledImage:(UIImage *)img insideButton:(UIButton *)btn {
// Check which dimension (width or height) to pay respect to and
// calculate the scale factor
CGFloat imgRatio = img.size.width / img.size.height,
btnRatio = btn.frame.size.width / btn.frame.size.height,
scaleFactor = (imgRatio > btnRatio
? img.size.width / btn.frame.size.width
: img.size.height / btn.frame.size.height;
// Create image using scale factor
UIImage *scaledImg = [UIImage imageWithCGImage:[img CGImage]
scale:scaleFactor
orientation:UIImageOrientationUp];
return scaledImg;
}
To implement this we would write:
UIImage *scaledImg = [self getScaledImage:myBtnImg insideButton:myBtn];
[myBtn setImage:scaledImg forState:UIControlStateNormal];
This should prevent the image from stretching in all control states. It worked for me, but let me know if it doesn't!
NOTE: Here we are addressing a problem relating to UIButton
, but the insideButton:
might as well be insideView:
, or whatever one would like to fit the image into.

- 1,394
- 10
- 22
This worked for me
[button.imageView setContentMode:UIViewContentModeScaleAspectFit];
Thanks to @ayreguitar for his comment

- 2,154
- 4
- 25
- 56
Here's an alternative answer in swift:
myButton.imageView?.contentMode = .ScaleAspectFit

- 944
- 1
- 13
- 18
Combining together a few different answers into one solution-- create a button with a custom type, set the button's imageView contentMode property, and set the image for the button (not the background image, which will still scale to fill).
//Objective-C:
UIImage *image = [UIImage imageNamed:"myImageName.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;
//Swift:
let image = UIImage(named: "myImageName.png")
let button = UIButton(type: .custom)
button.imageView?.contentMode = .scaleAspectFit
button.setImage(image, for: .normal)

- 802
- 10
- 9
ios 12. You need to add also the content Alignment
class FitButton: UIButton {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
self.imageView?.contentMode = .scaleAspectFill
self.contentHorizontalAlignment = .fill
self.contentVerticalAlignment = .fill
super.layoutSubviews()
}
}

- 3,751
- 31
- 32
btn.imageView.contentMode = UIViewContentModeScaleAspectFit;

- 71
- 9
-
While this code snippet may solve the question, [including an explanation](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. - [From review](https://stackoverflow.com/review/low-quality-posts/11679579) – Ferrybig Mar 18 '16 at 09:52
This answer is based on @WernerAltewischer's answer.
To avoid having connect my button to an IBOutlet to execute the code on it, I subclassed UIButton's class:
// .h
@interface UIButtonWithImageAspectFit : UIButton
@end
// .m
@implementation UIButtonWithImageAspectFit
- (void) awakeFromNib {
[self.imageView setContentMode:UIViewContentModeScaleAspectFit];
}
@end
Now create a custom button in your xib, and set its image (not the background image):
Then, set its class:
You're done!
Instead of
your button's image aspect fit is now as expected:
I had problems with the image not resizing proportionately so the way I fixed it was using edge insets.
fooButton.contentEdgeInsets = UIEdgeInsetsMake(10, 15, 10, 15);

- 6,951
- 8
- 60
- 104
Changing UIButton.imageView.contentMode
does not worked for me.
I solved the problem by setting the image to 'Background' property.
You can add ratio constraint if you need

- 625
- 4
- 11
UIView content modes apply to the corresponding CALayer's "content". This works for UIImageView
s because they set the CALayer
content to the corresponding CGImage
.
drawRect:
ultimately renders to the layer content.
A custom UIButton
(as far as I know) has no content (the rounded-rect style buttons might be rendered using content). The button has subviews: the background UIImageView
, the image UIImageView
, and the title UILabel
. Setting the contentMode
on the subviews may do what you want, but messing around with the UIButton
view hierarchy is a bit of a no-no.
This overlaps many of the other answers, but the solution for me was to
- set the
contentMode
of theUIImageView
for the button to.ScaleAspectFit
– which can either be done in the ”User Defined Runtime Attributes” in Interface Builder (ie.self.imageView.contentMode
, Number, 1) or in aUIButton
subclass; - disable ”Autoresize Subviews”;
- set ”Edge” to ”Image” and appropriate ”Top” and ”Bottom” values for ”Inset” (which might only be needed if you, like me, used a PDF as image).

- 877
- 1
- 9
- 15
Similar to @Guillaume, I have created a subclass of UIButton as a Swift-File. Then set my custom class in the Interface Builder:
And here the Swift file:
import UIKit
class TRAspectButton : UIButton {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.imageView?.contentMode = .ScaleAspectFit
}
}

- 1,638
- 18
- 18
You can use imageWithCGImage as shown above (but without the missing parentheses).
Also... millions of non-4.0 phones won't work with that code at all.

- 141
- 1
- 5
I had the same issue, but I couldn't get it to work (perhaps it's a bug with the SDK).
Eventually, as a workaround, I placed a UIImageView
behind my button and set the options I wanted on that, then simply placed a blank UIButton
on top of it.

- 2,800
- 2
- 23
- 22