如何使用 Bootstrap 设置 Stripe Elements 输入的样式?
Posted
技术标签:
【中文标题】如何使用 Bootstrap 设置 Stripe Elements 输入的样式?【英文标题】:How can I style a Stripe Elements input with Bootstrap? 【发布时间】:2018-02-12 19:48:34 【问题描述】:我正在构建一个使用 Stripe 处理付款的简单网站。我正在使用 Bootstrap 进行样式设置。当我使用 Stripe Elements 插入付款字段时,它们没有使用 Bootstrap 进行样式设置。如何将 Bootstrap 的样式应用于 Elements 支付字段?
【问题讨论】:
【参考方案1】:好的,所以我必须弄清楚这一点,因为我使用的是 Stripe.js v2,并且 Stripe 技术支持向我解释了安全漏洞,所以我觉得有义务切换到 Stripe.js v3 “Elements”。他们所说的是,与您的信用卡表单元素在同一页面上的任何 javascript 都可以获取敏感信用卡数据的值。我想如果一个人正在拉入外部脚本,这可能会发生......我想它一定已经发生了,否则他们不会关心它。无论如何,这就是我如何让我的 Stripe.js v3 元素与 Bootstrap 4 输入组一起工作。这是一个完整的工作示例,您只需要更改公钥。
默认的基于 jQuery 的示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Stripe.js v3 with Bootstrap 4 Test</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<style>
/* Blue outline on focus */
.StripeElement--focus
border-color: #80BDFF;
outline:0;
box-shadow: 0 0 0 .2rem rgba(0,123,255,.25);
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
/* Can't see what I type without this */
#card-number.form-control,
#card-cvc.form-control,
#card-exp.form-control
display:inline-block;
</style>
</head>
<body>
<div class="container-fluid">
<h1 class="mt-5">Stripe.js v3 with Bootstrap 4 (beta) Test</h1>
<div id="card-errors" role="alert"></div>
<div class="card">
<div class="card-body">
<form id="payment-form">
<label for="name">Name on Card</label>
<div class="input-group mb-2">
<div class="input-group-prepend">
<span class="input-group-text">A</span>
</div>
<input type="text" class="form-control" id="name">
<div class="input-group-append">
<span class="input-group-text">B</span>
</div>
</div>
<label for="card-number">Credit Card Number</label>
<div class="input-group mb-2">
<div class="input-group-prepend">
<span class="input-group-text">C</span>
</div>
<span id="card-number" class="form-control">
<!-- Stripe Card Element -->
</span>
<div class="input-group-append">
<span class="input-group-text">D</span>
</div>
</div>
<label for="card-cvc">CVC Number</label>
<div class="input-group mb-2">
<div class="input-group-prepend">
<span class="input-group-text">E</span>
</div>
<span id="card-cvc" class="form-control">
<!-- Stripe CVC Element -->
</span>
</div>
<label for="card-exp">Expiration</label>
<div class="input-group mb-2">
<span id="card-exp" class="form-control">
<!-- Stripe Card Expiry Element -->
</span>
<div class="input-group-append">
<span class="input-group-text">F</span>
</div>
</div>
<button id="payment-submit" class="btn btn-primary mt-1">Submit Payment</button>
</form>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src="https://js.stripe.com/v3/"></script>
<script>
$(document).ready(function()
// Create a Stripe client
var stripe = Stripe('pk_test_XxXxXxXxXxXxXxXxXxXxXxXx');
// Create an instance of Elements
var elements = stripe.elements();
// Try to match bootstrap 4 styling
var style =
base:
'lineHeight': '1.35',
'fontSize': '1.11rem',
'color': '#495057',
'fontFamily': 'apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif'
;
// Card number
var card = elements.create('cardNumber',
'placeholder': '',
'style': style
);
card.mount('#card-number');
// CVC
var cvc = elements.create('cardCvc',
'placeholder': '',
'style': style
);
cvc.mount('#card-cvc');
// Card expiry
var exp = elements.create('cardExpiry',
'placeholder': '',
'style': style
);
exp.mount('#card-exp');
// Submit
$('#payment-submit').on('click', function(e)
e.preventDefault();
var cardData =
'name': $('#name').val()
;
stripe.createToken(card, cardData).then(function(result)
console.log(result);
if(result.error && result.error.message)
alert(result.error.message);
else
alert(result.token.id);
);
);
);
</script>
</body>
</html>
我仅在 Firefox、Chrome 和 android 上的 Chrome 中进行了测试。似乎工作正常。如果您遇到任何问题,请告诉我。
可选的基于 Vue.js 的示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Stripe.js v3 with Bootstrap 4 and Vue.js</title>
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css"/>
<style>
/* This background color not essential for the example */
html, body
background:#999;
/* Padding for Stripe Element containers */
.stripe-element-container
padding-top: .55rem;
padding-bottom: .50rem;
/* Blue outline on focus */
.StripeElement--focus
border-color: #80BDFF;
outline:0;
box-shadow: 0 0 0 .2rem rgba(0,123,255,.25);
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
/* Can't see what I type without this */
#card-number.form-control,
#card-cvc.form-control,
#card-exp.form-control
display:inline-block;
</style>
</head>
<body>
<div id="app">
<stripe-form inline-template>
<div class="container-fluid">
<div class="row">
<div class="col-md-4 offset-md-4 pt-5">
<div class="card">
<div class="card-header">
<h3 class="mb-0">Pay Now</h3>
</div>
<div class="card-body">
<div v-bind:class="alert: activeError, 'alert-danger': activeError" role="alert" v-html="errorText"></div>
<form>
<div class="form-group mb-4">
<label for="name">Name on Card</label>
<input type="text" class="form-control" v-model="ccName" />
</div>
<div class="form-group">
<label for="card-number">Credit Card Number</label>
<span id="card-number" class="form-control stripe-element-container">
<!-- Stripe Card Element -->
</span>
</div>
<div class="form-group">
<label for="card-cvc">CVC Number</label>
<span id="card-cvc" class="form-control stripe-element-container">
<!-- Stripe CVC Element -->
</span>
</div>
<div class="form-group">
<label for="card-exp">Expiration</label>
<span id="card-exp" class="form-control stripe-element-container">
<!-- Stripe Card Expiry Element -->
</span>
</div>
<button @click.prevent="paymentSubmit" class="btn btn-primary mt-1 float-right">Submit Payment</button>
</form>
</div>
</div>
</div>
</div>
</div>
</stripe-form>
<modal></modal>
</div>
<script src="https://unpkg.com/vue@2.5.13/dist/vue.js"></script>
<script src="https://unpkg.com/babel-polyfill@latest/dist/polyfill.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.js"></script>
<script src="https://js.stripe.com/v3/"></script>
<script>
// Your Stripe public key
const stripePublicKey = 'pk_test_XxXxXxXxXxXxXxXxXxXxXxXx';
/**
* Class allows firing of events and
* listening of events between components
*/
window.Events = new class
constructor()
this.vue = new Vue();
fire( event, data = null )
this.vue.$emit( event, data );
listenFor( event, callback )
this.vue.$on( event, callback );
/**
* See: https://bootstrap-vue.js.org/docs/components/modal/
*/
Vue.component('modal',
template: `
<div>
<b-modal ref="myModalRef" ok-only ok-title="Close" v-bind:title="title">
<p class="mb-0"> body </p>
</b-modal>
</div>
`,
data: function()
return
title: '',
body: ''
,
methods:
showModal ()
this.$refs.myModalRef.show()
/* This not needed for this example
,
hideModal ()
this.$refs.myModalRef.hide()
*/
,
created()
Events.listenFor('modalShow', ( data ) =>
this.title = data.title;
this.body = data.message;
this.showModal();
);
);
Vue.component('stripe-form',
data: function()
return
activeError: false,
errorText: '',
ccName: '',
stripe: null,
card: null,
cvc: null,
exp: null
,
methods:
paymentSubmit: function()
let cardData =
'name': this.ccName
;
// Ensure the name field is not empty
if( cardData.name.trim() == '' )
// Show an error
this.activeError = true;
this.errorText = '<b>Submission Error:</b><br />Name is required.';
// Abort !!
return;
this.stripe.createToken( this.card, cardData).then( (result) =>
if(result.error && result.error.message)
// Show any errors
this.activeError = true;
this.errorText = '<b>Submission Error:</b><br />' + result.error.message;
else
/**
* Success message in modal.
* This is normally where you'd post to your server,
* and have it actually attempt the credit card transaction
* using the token ID that was just received.
*/
Events.fire('modalShow',
'title': 'Success',
'message': result.token.id
);
// Clear the form
this.activeError = false;
this.errorText = '';
this.ccName = '';
// Stripe elements must be cleared in a special way
this.card.clear();
this.cvc.clear();
this.exp.clear();
);
,
mounted: function()
// Create a Stripe client
this.stripe = Stripe( stripePublicKey );
// Create an instance of Elements
const elements = this.stripe.elements();
/**
* Try to match bootstrap 4 styling.
* --------------------------------
* fontSize was in rem units, but Stripe says that it should be in pixels.
*/
const style =
base:
'fontSize': '16px',
'color': '#495057',
'fontFamily': 'apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif'
;
// Card number
this.card = elements.create('cardNumber',
'placeholder': '',
'style': style
);
this.card.mount('#card-number');
// CVC
this.cvc = elements.create('cardCvc',
'placeholder': '',
'style': style
);
this.cvc.mount('#card-cvc');
// Card expiry
this.exp = elements.create('cardExpiry',
'placeholder': '',
'style': style
);
this.exp.mount('#card-exp');
);
new Vue( el: '#app' );
</script>
</body>
</html>
这个 Vue.js 示例可以从一些工作中受益,但可能会帮助您入门。
【讨论】:
这对我来说看起来很棒!你肯定抓住了一些我错过的风格。 非常感谢!为我工作! 这很好,我将如何改变错误的样式? 这是一个简单的 Codelply 我创建的 codeply.com/p/PPX9p3vKEL【参考方案2】:在深入研究文档后,我发现 https://stripe.com/docs/stripe.js#the-element-container 说“你 应该为您安装元素的容器设置样式,就好像它是 在您的页面上。”
通过将 Bootstrap 的 form-control
类添加到我正在安装元素的 <div>
中,该字段看起来几乎与任何其他 Bootstrap 样式的输入字段一样:
<div id="card-element" class="form-control"></div>
由于某种原因,场地的高度不太匹配,但经过反复试验,我明白了 与:
var stripe = Stripe('your_key');
var elements = stripe.elements();
var card = elements.create('card', style:
base:
lineHeight: '1.429'
);
card.mount('#card-element');
【讨论】:
这是对的,但你还需要在元素获得焦点时应用边框颜色。此外,如果您正在使用 Bootstrap 4 beta 并尝试使用输入组,那么您必须更改元素 CSS 以使其为display:block
而不是 display:flex
。我有一个工作演示......但这并不是你问题的真正答案......除非它是。
好点!这听起来确实像答案:) 我很想看演示。
就我而言,form-control
正在以某种方式被删除。
很简单。谢谢。
我尝试了这个,并从 stripe 收到一条消息,说不建议更改 lineHeight,因为报告的各种浏览器上的视觉不一致。它建议填充元素容器。【参考方案3】:
这就是我们使用
所需的全部内容 <div class="form-group">
<label for="card-element">Credit or debit card</label>
<div id="card-element" class="form-control" style='height: 2.4em; padding-top: .7em;'>
<!-- A Stripe Element will be inserted here. -->
</div>
</div>
【讨论】:
非常简单。 javascript 是什么样的? 你只能通过内联css对特定区域进行样式化,其余的需要通过JS来完成。【参考方案4】:添加另一个答案,因为我觉得这里最简单的答案有点不完整。添加了错误显示和用于将令牌发送到后端的 JavaScript,以防您想这样做。
这个 HTML(来自他们的默认文档,添加了 Bootstrap 4 元素)
<form action="/charge" method="post" id="payment-form">
<div class="form-group">
<label for="card-element">
Credit or debit card
</label>
<div id="card-element" class="form-control">
<!-- A Stripe Element will be inserted here. -->
</div>
<!-- Used to display Element errors. -->
<div id="card-errors" role="alert"></div>
</div>
<button>Submit Payment</button>
</form>
这是 JavaScript(同样来自他们的默认文档,但我在这里使用 jQuery,但您不必这样做)
<script src="https://js.stripe.com/v3/"></script>
<script>
(function ($)
// Set your publishable key: remember to change this to your live publishable key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
var stripe = Stripe('yourPublishableKeyHere');
var elements = stripe.elements();
// Custom styling can be passed to options when creating an Element.
var style =
base:
// Add your base input styles here. For example:
fontSize: '16px',
color: '#32325d',
,
;
// Create an instance of the card Element.
var card = elements.create('card', style: style);
// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');
// Create a token or display an error when the form is submitted.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event)
event.preventDefault();
stripe.createToken(card).then(function(result)
if (result.error)
// Inform the customer that there was an error.
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
else
// Send the token to your server.
stripeTokenHandler(result.token);
);
);
function stripeTokenHandler(token)
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
)(jQuery);
</script>
【讨论】:
非常感谢。这个例子让我的生活变得轻松多了!【参考方案5】:改进其他答案,我得到了以下解决方案。不过,带上一粒盐。 .StripeElement--focus
和 .card-element-disabled
的 CSS 是从 Bootstrap 复制的,因此您可能希望从您正在使用的版本中获取它们(我想我有 4.4)。
另外,我没有复制支付逻辑,因为它特定于我的应用程序,但是当按下按钮并且 JavaScript 开始处理内容时我调用 disable_form
,当 JavaScript 完成并且表单可以是 enable_form
重新启用(可能是因为出现错误,否则你只是转到另一个页面)。
<style>
.StripeElement--focus
color: #495057;
background-color: #fff;
border-color: #80bdff;
outline: 0;
box-shadow: 0 0 0 .2rem rgba(0,123,255,.25);
.card-element-disabled
background-color: #e9ecef;
opacity: 1;
#card-element
display: flex;
align-items: center;
#card-element div
flex-grow: 1;
#card-element-error
color: #ff0000;
</style>
<script>
function disable_form()
$(".form-control").prop('disabled', true);
card.update(disabled: true);
$("#submit-btn").prop('disabled', true).html("Loading");
$("#card-element").addClass('card-element-disabled');
function enable_form()
$(".form-control").prop('disabled', false);
card.update(disabled: false);
$("#submit-btn").prop('disabled', false).html("Submit");
$("#card-element").removeClass('card-element-disabled');
var stripe = Stripe(' stripe_publishable_key ');
var elements = stripe.elements();
var card = elements.create('card');
function setup_stripe()
card.mount('#card-element');
setTimeout(setup_stripe, 0);
</script>
<form id="payment-form">
<!-- all other fields -->
<div class="form-group">
<label for="card-element">Card number</label>
<div id="card-element" class="form-control"></div>
</div>
<div id="card-element-error" role="alert"></div>
<button type="submit" class="btn btn-primary" id="submit-btn">Submit</button>
</form>
【讨论】:
【参考方案6】:我正在使用带有 react 的条带,并且我试图在父容器上使用类,但它对我不起作用。所以,我最终为容器使用了内联样式。 这是对我有用的最终代码。
const containerStyles =
border: '1px solid #d3d3d3',
padding: '5px 10px 5px 10px',
borderRadius: '4px',
width: '100%', ;
const cardNumberElementOptions =
style:
base:
fontSize: '14px',
lineHeight: '45px',
,
,
placeholder: 'Card Number',
;
<div style=containerStyles>
<CardNumberElement options=cardNumberElementOptions />
</div>
【讨论】:
以上是关于如何使用 Bootstrap 设置 Stripe Elements 输入的样式?的主要内容,如果未能解决你的问题,请参考以下文章