Let Safari Draw the Apple Pay Button
Apple Pay buttons should look like Apple Pay buttons. In Safari, CSS can ask the browser to draw the approved control, so there is no need to recreate the logo and spacing by hand.
The browser-provided button also gives you a set of transaction-specific labels. Choose the type that describes the action rather than using buy for everything.
Available button types
Apple Pay on the Web version 2 introduced:
buy— “Buy with” followed by the Apple Pay logo;donate— “Donate with” and the logo, available from iOS 10.2;plain— the Apple Pay logo without text;set-up— a prompt to set up a card for Apple Pay.
Version 4 added:
book;check-out;subscribe.
Version 10 added:
add-money;contribute;order;reload;rent;support;tip;top-up.
Version 12 added continue, which displays “Continue with Apple Pay” and the logo. These version notes describe availability when this post was written in 2021; check Apple’s current documentation when targeting newer button types.
The browser-rendered button
The basic version needs an element and two Apple-specific CSS properties:
<div class="apple-pay-button apple-pay-button-black"></div>
.apple-pay-button {
display: inline-block;
-webkit-appearance: -apple-pay-button;
-apple-pay-button-type: donate;
}
.apple-pay-button-black {
-apple-pay-button-style: black;
}
.apple-pay-button-white {
-apple-pay-button-style: white;
}
.apple-pay-button-white-with-line {
-apple-pay-button-style: white-outline;
}
Change -apple-pay-button-type to the action you need. The style can be black, white, or white with an outline, depending on the background around the button.
In production, the clickable control should have the correct button semantics and be connected to a working Apple Pay flow. This example concentrates only on its appearance.
A fallback for older Safari versions
Older versions of macOS and iOS did not support -webkit-appearance: -apple-pay-button. @supports can separate the native rendering from a manually drawn plain button:
<div class="apple-pay-button apple-pay-button-white"></div>
@supports (-webkit-appearance: -apple-pay-button) {
.apple-pay-button {
display: inline-block;
-webkit-appearance: -apple-pay-button;
}
.apple-pay-button-black {
-apple-pay-button-style: black;
}
.apple-pay-button-white {
-apple-pay-button-style: white;
}
.apple-pay-button-white-with-line {
-apple-pay-button-style: white-outline;
}
}
@supports not (-webkit-appearance: -apple-pay-button) {
.apple-pay-button {
display: inline-block;
box-sizing: border-box;
min-width: 200px;
min-height: 32px;
max-height: 64px;
padding: 0;
border-radius: 5px;
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: 100% 60%;
}
.apple-pay-button-black {
background-color: black;
background-image: -webkit-named-image(apple-pay-logo-white);
}
.apple-pay-button-white {
background-color: white;
background-image: -webkit-named-image(apple-pay-logo-black);
}
.apple-pay-button-white-with-line {
border: 0.5px solid black;
background-color: white;
background-image: -webkit-named-image(apple-pay-logo-black);
}
}
The fallback uses Safari’s named Apple Pay logo image and draws the surrounding button with ordinary CSS. It is more code, which is a good reason to prefer the native appearance whenever it is available.
A button with text in the fallback
If the fallback also needs a label, keep the text and logo as separate elements. Safari hides them when it can render the complete control itself:
<div class="apple-pay-button-with-text apple-pay-button-white-with-text">
<span class="text">Buy with</span>
<span class="logo"></span>
</div>
@supports (-webkit-appearance: -apple-pay-button) {
.apple-pay-button-with-text {
display: inline-block;
-webkit-appearance: -apple-pay-button;
-apple-pay-button-type: buy;
}
.apple-pay-button-with-text > * {
display: none;
}
.apple-pay-button-black-with-text {
-apple-pay-button-style: black;
}
.apple-pay-button-white-with-text {
-apple-pay-button-style: white;
}
.apple-pay-button-white-with-line-with-text {
-apple-pay-button-style: white-outline;
}
}
@supports not (-webkit-appearance: -apple-pay-button) {
.apple-pay-button-with-text {
--apple-pay-scale: 1;
display: inline-flex;
justify-content: center;
box-sizing: border-box;
min-width: 200px;
min-height: 32px;
max-height: 64px;
padding: 0;
border-radius: 5px;
font-size: 12px;
}
.apple-pay-button-black-with-text {
background-color: black;
color: white;
}
.apple-pay-button-white-with-text {
background-color: white;
color: black;
}
.apple-pay-button-white-with-line-with-text {
border: 0.5px solid black;
background-color: white;
color: black;
}
.apple-pay-button-with-text.apple-pay-button-black-with-text > .logo {
background-color: black;
background-image: -webkit-named-image(apple-pay-logo-white);
}
.apple-pay-button-with-text.apple-pay-button-white-with-text > .logo,
.apple-pay-button-with-text.apple-pay-button-white-with-line-with-text > .logo {
background-color: white;
background-image: -webkit-named-image(apple-pay-logo-black);
}
.apple-pay-button-with-text > .text {
align-self: center;
margin-right: calc(2px * var(--apple-pay-scale));
font-family: -apple-system, sans-serif;
font-size: calc(1em * var(--apple-pay-scale));
font-weight: 300;
}
.apple-pay-button-with-text > .logo {
width: calc(35px * var(--apple-pay-scale));
height: 100%;
margin-left: calc(2px * var(--apple-pay-scale));
border: 0;
background-repeat: no-repeat;
background-position: 0 50%;
background-size: 100% 60%;
}
}
The original version of this fallback mixed --scale and --apple-pay-scale; using one variable keeps the text and logo sizing in step.
For current Safari versions, I would start with the native CSS button and add a fallback only if analytics show that the older systems matter. Payment controls already have enough ways to go wrong without maintaining a hand-drawn version nobody uses.