Developer Guide

Popup Customization Guide

Learn how to customize the COD payment selection popup appearance using CSS for your Shopify store.

12 min readLast updated: 2026-01-26

This guide is for developers who want to customize the COD payment selection popup appearance using CSS.


Overview

The PenguinCOD popup uses a native HTML <dialog> element for reliable display across all Shopify themes. Customization is done through CSS added to your theme.

Where to add CSS:

  • Theme Editor > Edit Code > base.css or theme.css
  • Or create a new file like cod-custom.css and include it in theme.liquid

Hiding Payment Options

Hide Full Payment Option

/* Hide the Full Payment option */
#codOptionFull {
  display: none !important;
}

Hide Partial Prepaid + COD Option

/* Hide the Partial Prepaid option */
#codOptionPartial {
  display: none !important;
}

Hide Full COD (Cash on Delivery) Option

/* Hide the Full COD option */
#codOptionFullCod {
  display: none !important;
}

Hide Based on Cart Value (Advanced)

Add this to your theme's JavaScript:

// In theme.liquid before </body>
<script>
(function() {
  // Example: Hide Full Payment for carts over a certain value
  var style = document.createElement('style');
  
  fetch('/cart.js')
    .then(function(res) { return res.json(); })
    .then(function(cart) {
      var cartTotal = cart.total_price / 100;
      
      // Hide Full Payment for carts over 50000
      if (cartTotal > 50000) {
        style.textContent = '#codOptionFull { display: none !important; }';
        document.head.appendChild(style);
      }
    });
})();
</script>

CSS Customization

Popup Container

/* Main popup modal */
.cod-modal {
  max-width: 500px !important;
  border-radius: 20px !important;
  box-shadow: 0 30px 60px rgba(0,0,0,0.3) !important;
}

/* Popup overlay/backdrop */
.cod-dialog::backdrop {
  background: rgba(0, 0, 0, 0.8) !important;
}

Payment Options

/* All payment option cards */
.cod-option {
  padding: 20px !important;
  border-radius: 12px !important;
  margin-bottom: 12px !important;
}

/* Selected option styling */
.cod-option.selected {
  background: #f0f8ff !important;
  border-color: #0066cc !important;
  border-width: 2px !important;
}

/* Option title */
.cod-option-title {
  font-size: 18px !important;
  font-weight: 700 !important;
}

/* Option subtitle/description */
.cod-option-desc {
  font-size: 13px !important;
  color: #888 !important;
}

Amounts Display

/* Primary amount (e.g., "Rs. 1,299") */
.cod-amount-primary {
  font-size: 20px !important;
  font-weight: 700 !important;
  color: #000 !important;
}

/* Secondary amount (e.g., "+Rs. 1,399 COD") */
.cod-amount-secondary {
  font-size: 14px !important;
  color: #666 !important;
}

/* Discount badge */
.cod-discount-badge {
  background: #e8f5e9 !important;
  color: #2e7d32 !important;
  font-size: 12px !important;
  padding: 4px 8px !important;
  border-radius: 4px !important;
}

CTA Button

/* Proceed to Checkout button */
.cod-btn {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
  height: 56px !important;
  font-size: 16px !important;
  font-weight: 600 !important;
  border-radius: 12px !important;
}

/* Button disabled state */
.cod-btn:disabled {
  background: #ccc !important;
  cursor: not-allowed !important;
}

Radio Buttons

/* Radio button size */
.cod-radio {
  width: 24px !important;
  height: 24px !important;
}

/* Selected radio inner circle */
.cod-option.selected .cod-radio-inner {
  width: 14px !important;
  height: 14px !important;
  background: #0066cc !important;
}

Header Customization

The popup has a dark header showing the cart summary.

Header Container

/* Main header background */
.cod-popup-header {
  background: #1a1a2e !important;
  padding: 20px !important;
}

/* Header row layout */
.cod-popup-header-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

Cart Summary in Header

/* Cart icon */
.cod-cart-icon {
  font-size: 20px !important;
}

/* Cart total amount */
.cod-popup-header-total {
  font-size: 22px !important;
  font-weight: 700 !important;
}

/* Item count text */
.cod-popup-header-items {
  font-size: 14px !important;
  opacity: 0.8 !important;
}

Verified Phone Indicator

When OTP is verified, a phone number appears in the header:

/* Verified phone container */
.cod-popup-header-verified {
  border-top: 1px dashed rgba(255,255,255,0.5) !important;
  padding-top: 12px !important;
  margin-top: 12px !important;
}

/* Green checkmark */
.cod-verified-tick {
  color: #22c55e !important;
  background: rgba(34,197,94,0.3) !important;
  width: 24px !important;
  height: 24px !important;
}

OTP Screen Customization

If OTP verification is enabled, users see phone input and OTP verification screens.

Phone Input Screen

/* Phone input wrapper */
.cod-phone-input-wrapper {
  display: flex;
  gap: 12px !important;
  margin-bottom: 24px !important;
}

/* Country code input */
.cod-country-code-input {
  width: 90px !important;
  padding: 14px !important;
  border: 2px solid #e0e0e0 !important;
  border-radius: 10px !important;
  background: #f8f8f8 !important;
  font-size: 16px !important;
}

/* Phone number input */
.cod-phone-input {
  flex: 1;
  padding: 14px 16px !important;
  border: 2px solid #e0e0e0 !important;
  border-radius: 10px !important;
  background: #f8f8f8 !important;
  font-size: 16px !important;
}

/* Focus state for inputs */
.cod-phone-input:focus,
.cod-country-code-input:focus {
  border-color: #000 !important;
  outline: none !important;
}

OTP Digit Inputs

/* OTP digit input boxes */
.cod-otp-digit {
  width: 56px !important;
  height: 64px !important;
  text-align: center;
  font-size: 28px !important;
  font-weight: 600 !important;
  border: 2px solid #e0e0e0 !important;
  border-radius: 10px !important;
  background: #f8f8f8 !important;
}

.cod-otp-digit:focus {
  border-color: #000 !important;
  outline: none !important;
}

/* Container for OTP digits */
.cod-otp-input-wrapper {
  display: flex;
  justify-content: center;
  gap: 12px !important;
}

OTP Error Messages

/* Error message styling */
.cod-otp-error {
  color: #d32f2f !important;
  font-size: 14px !important;
  text-align: center;
  margin-bottom: 16px !important;
  background: #ffebee !important;
  padding: 10px !important;
  border-radius: 8px !important;
}

Resend OTP Section

/* Resend text container */
.cod-otp-resend {
  text-align: center;
  font-size: 14px !important;
  color: #666 !important;
  margin-bottom: 20px !important;
}

/* Resend button */
.cod-otp-resend-btn {
  color: #4a90d9 !important;
  font-weight: 600 !important;
  background: none;
  border: none;
  cursor: pointer;
}

.cod-otp-resend-btn:disabled {
  color: #999 !important;
  cursor: not-allowed;
}

Skip OTP Button

/* Skip OTP / Pay Full Amount button */
.cod-otp-skip-btn {
  color: #4a90d9 !important;
  font-size: 15px !important;
  font-weight: 500 !important;
  padding: 12px 20px !important;
}

/* Divider above skip button */
.cod-otp-divider {
  color: #999 !important;
  font-size: 13px !important;
  margin: 16px 0 !important;
}

.cod-otp-divider::before,
.cod-otp-divider::after {
  border-color: #e0e0e0 !important;
}

Edit Phone Button

/* Edit phone number button on OTP screen */
.cod-otp-edit-btn {
  color: #4a90d9 !important;
  font-weight: 500 !important;
  font-size: 14px !important;
}

CSS Variables Reference

The popup uses CSS custom properties (variables) that can be overridden globally. Override these on the .cod-dialog selector:

.cod-dialog {
  /* Main colors */
  --cod-primary: #1a1a1a !important;
  --cod-accent: #4a90d9 !important;
  
  /* Popup background */
  --cod-popup-bg: #ffffff !important;
  
  /* Header */
  --cod-header-bg: #374151 !important;
  
  /* Text colors */
  --cod-title-color: #1a1a1a !important;
  --cod-option-title: #1a1a1a !important;
  --cod-option-subtitle: #666666 !important;
  
  /* Option states */
  --cod-selected-border: #000000 !important;
  --cod-selected-bg: #f8f8f8 !important;
  --cod-unselected-border: #e0e0e0 !important;
  
  /* Radio buttons */
  --cod-radio-selected: #000000 !important;
  --cod-radio-unselected: #cccccc !important;
  
  /* CTA Button */
  --cod-cta-bg: #5c2d2d !important;
  --cod-cta-text: #ffffff !important;
  
  /* Discount badge */
  --cod-discount-color: #16a34a !important;
  
  /* OTP inputs */
  --cod-otp-input-bg: #f5f5f5 !important;
  --cod-otp-input-border: #e0e0e0 !important;
  --cod-otp-input-focus: #000000 !important;
  --cod-otp-resend: #4a90d9 !important;
  --cod-otp-error: #d32f2f !important;
}

Additional Classes & States

Disabled Option State

When an option is unavailable (e.g., cart value restrictions):

/* Disabled/unavailable option */
.cod-option.cod-disabled {
  opacity: 0.4 !important;
  cursor: not-allowed !important;
}

/* Unavailable message text */
.cod-unavailable {
  color: #cc0000 !important;
  font-size: 12px !important;
  margin-top: 8px !important;
}

COD Fee Note

/* Fee note below amounts (e.g., "COD Shipping Fee Rs. 50") */
.cod-fee-note {
  font-size: 11px !important;
  color: #888 !important;
  font-style: italic !important;
  margin-top: 4px !important;
}

Footer & Branding

/* Footer container */
.cod-footer {
  padding: 24px !important;
  border-top: 1px solid #e5e5e5 !important;
}

/* "Secured by PenguinCOD" text */
.cod-powered-by {
  font-size: 11px !important;
  color: #aaa !important;
  text-align: right !important;
  margin-top: 16px !important;
}

/* Hide the branding completely */
.cod-powered-by {
  display: none !important;
}

Screen Title

/* Title container */
.cod-screen-title {
  padding: 24px 24px 0 24px !important;
}

/* Main title text */
.cod-title {
  font-size: 20px !important;
  font-weight: 700 !important;
  color: #1a1a1a !important;
}

Loading State

When checking collection eligibility:

/* Option in checking/loading state */
.cod-option.cod-checking {
  opacity: 0.6 !important;
}

/* Loading spinner (appears on right side) */
.cod-option.cod-checking::after {
  border-color: #e0e0e0 !important;
  border-top-color: #333 !important;
}

Button Loading State

/* Button while processing */
.cod-btn.cod-loading {
  background: #999 !important;
}

Animation Customization

Popup Open Animation

/* Fade in animation for backdrop */
@keyframes cod-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Slide in animation for modal */
@keyframes cod-slide-in {
  from { 
    transform: scale(0.9) translateY(20px); 
    opacity: 0; 
  }
  to { 
    transform: scale(1) translateY(0); 
    opacity: 1; 
  }
}

/* Customize animation duration */
.cod-dialog[open] {
  animation: cod-fade-in 0.3s ease forwards !important;
}

.cod-dialog[open] .cod-modal {
  animation: cod-slide-in 0.4s ease forwards !important;
}

Disable Animations

/* Remove all popup animations */
.cod-dialog[open],
.cod-dialog[open] .cod-modal {
  animation: none !important;
}

Element IDs Reference

Use these IDs to target specific elements with CSS:

Main Popup Elements

| Element ID | Description | |------------|-------------| | codDialog | Main dialog element (use .cod-dialog class instead) | | codPopupHeader | Dark header container | | codScreenTitle | Screen title container | | codTitle | Main title text (h2) |

Header Elements

| Element ID | Description | |------------|-------------| | codHeaderTotal | Cart total amount in header | | codHeaderItems | Item count text in header | | codHeaderVerified | Verified phone container (hidden until verified) | | codHeaderVerifiedPhone | Verified phone number display |

Payment Options

| Element ID | Description | |------------|-------------| | codOptionFull | Full Payment option container | | codOptionPartial | Partial Prepaid option container | | codOptionFullCod | Full COD option container | | codFullAmountValue | Full Payment amount display | | codDiscountBadge | Full Payment discount badge | | codPartialNowValue | Partial Prepaid "Now" amount | | codPartialCodValue | Partial Prepaid "COD" amount | | codPartialDiscountBadge | Partial Prepaid discount badge | | codPartialFeeNote | Partial Prepaid COD fee note | | codPartialUnavailable | Partial Prepaid unavailable message | | codFullCodValue | Full COD amount display | | codFullCodFeeNote | Full COD fee note | | codFullCodUnavailable | Full COD unavailable message | | codProceed | Proceed to Checkout button |

OTP Phone Screen

| Element ID | Description | |------------|-------------| | codOtpPhoneScreen | Phone input screen container | | codOtpPhoneSubtitle | Subtitle text on phone screen | | codCountryCodeInput | Country code input field | | codPhoneInput | Phone number input field | | codPhoneError | Phone validation error message | | codSendOtp | Send OTP button | | codOtpDivider | "or" divider element | | codSkipOtp | Skip OTP button (phone screen) |

OTP Verification Screen

| Element ID | Description | |------------|-------------| | codOtpVerifyScreen | OTP verification screen container | | codOtpVerifySubtitle | "Code sent to..." subtitle | | codEditPhone | Edit phone number button | | codOtp1 - codOtp4 | Individual OTP digit inputs | | codOtpError | OTP verification error message | | codResendText | "Didn't receive?" text | | codResendOtp | Resend OTP button | | codResendCooldown | Cooldown timer display | | codVerifyOtp | Verify OTP button | | codSkipOtpVerify | Skip OTP button (verify screen) |

Screen Containers

| Element ID | Description | |------------|-------------| | codOtpPhoneScreen | Phone input screen | | codOtpVerifyScreen | OTP verification screen | | codPaymentScreen | Payment options screen |


Examples

Example 1: Dark Theme Popup

.cod-modal {
  background: #1a1a2e !important;
}

.cod-option {
  background: #16213e !important;
  border-color: #0f3460 !important;
}

.cod-option.selected {
  background: #0f3460 !important;
  border-color: #e94560 !important;
}

.cod-option-title {
  color: #ffffff !important;
}

.cod-option-desc {
  color: #a0a0a0 !important;
}

.cod-amount-primary,
.cod-amount-secondary {
  color: #ffffff !important;
}

.cod-btn {
  background: #e94560 !important;
}

.cod-dialog::backdrop {
  background: rgba(0, 0, 0, 0.9) !important;
}

Example 2: Rounded Modern Style

.cod-modal {
  border-radius: 24px !important;
  overflow: hidden !important;
}

.cod-option {
  border-radius: 16px !important;
  transition: all 0.2s ease !important;
}

.cod-option:hover {
  transform: translateY(-2px) !important;
  box-shadow: 0 4px 12px rgba(0,0,0,0.1) !important;
}

.cod-btn {
  border-radius: 16px !important;
  font-weight: 700 !important;
  text-transform: uppercase !important;
  letter-spacing: 1px !important;
}

Example 3: Minimal Clean Style

.cod-modal {
  border-radius: 8px !important;
  box-shadow: 0 4px 20px rgba(0,0,0,0.15) !important;
}

.cod-option {
  border-radius: 8px !important;
  border-width: 1px !important;
}

.cod-option.selected {
  border-width: 1px !important;
  background: transparent !important;
}

.cod-discount-badge {
  background: transparent !important;
  color: #22c55e !important;
  padding: 0 !important;
}

.cod-btn {
  border-radius: 8px !important;
  background: #000 !important;
}

Important Notes

  1. Prices are validated server-side: The amounts shown in the popup are for display only. Actual checkout prices are calculated securely on Shopify's servers and cannot be manipulated through CSS or JavaScript.

  2. Use !important: Due to specificity, you may need !important to override default styles.

  3. Test on mobile: Always test your customizations on mobile devices as the popup is responsive.

  4. Theme updates: Custom CSS may need adjustment after theme updates.

  5. Don't hide all options: Ensure at least one payment option remains visible for customers to complete checkout.

  6. Checkout page cannot be customized: This guide covers the payment selection popup only. The actual Shopify checkout page styling requires Shopify Plus (checkout.liquid/Checkout Extensibility) or Shopify's built-in checkout branding editor. PenguinCOD does not control checkout page appearance.

  7. OTP screens only appear if enabled: The phone/OTP verification screens are only shown when OTP verification is enabled in your PenguinCOD dashboard.

  8. CSS class naming: All PenguinCOD classes use the .cod- prefix to avoid conflicts with theme styles.


Support

For customization assistance:

  • Email: deepumpanicker@gmail.com