英文:
How to style Stripe.js custom element like my other bootstrap floating label elements
问题
我想要为我的Stripe.js元素(卡号、CVC、有效期)添加浮动标签样式,以保持与我使用的其他bootstrap浮动标签一致。我正在使用ngx-stripe作为Stripe.js的封装器。我已经成功使它们看起来与我的其他bootstrap元素类似,但在获得焦点时它们不会浮动。Stackblitz示例。
Stripe在这里提供了有关浮动标签外观的一些信息,但在尝试不同的方法后,没有任何变化!所以我可能没有正确使用它,或者我的bootstrap类可能与Stripe的CSS发生冲突?
- https://stripe.com/docs/elements/appearance-api?platform=web#form-inputs---floating-labels
- https://stripe.com/docs/elements/appearance-api?platform=web#others
这是使用bootstrap浮动类的卡号元素示例:
<div class="form-floating mb-3">
<div id="floatingNumber" class="form-control stripe-form-control" placeholder="例如 1111 1111 1111 1111"></div>
<label for="floatingNumber">Card Number</label>
</div>
你可以看到标签和文本的位置是固定的,它们不会浮动。
这是我的已经设置好的Stackblitz。
我尝试过的方法:
- 添加bootstrap浮动类
- 在创建Stripe元素时,在外观中添加了appearance: { labels: 'floating' }
- 添加"class="stripe-form-control""作为类 - 在Stripe网站的某个地方找到的
英文:
I'd like to style my Stripe.js elements (card number, Cvc, Expiry) with floating labels, to be consistent with my other bootstrap floating labels I'm using ngx-stripe as a wrapper around Stripe.js. I've been able to make them look similar to my other bootstrap elements, but they don't float when focus is given. Stackblitz here.
Stripe has some info on floating label appearances here, but after attempting different things, nothing changed! So I might not be using it correctly or my bootstrap classes might be interfering with the Stripe CSS?
- https://stripe.com/docs/elements/appearance-api?platform=web#form-inputs---floating-labels
- https://stripe.com/docs/elements/appearance-api?platform=web#others
Here is what my card number element looks like using bootstrap's floating classes:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
<div class="form-floating mb-3">
<div id="floatingNumber" class="form-control stripe-form-control" placeholder="ex. 1111 1111 1111 1111"></div>
<label for="floatingNumber">Card Number</label>
</div>
<!-- end snippet -->
Image from my Stackblitz
You can see the positions of the label and text are fixed, they don't float.
Here is my Stackblitz that has it set up.
Here is what I tried.
- Added bootstrap floating classes
- When creating the Stripe elements I added appearance: { labels: 'floating' } in the appearance
- Added "stripe-form-control" as a class - found somewhere on Stripe website
答案1
得分: 1
我不是一个Angular、Bootstrap或Stripe.js的专家,但我刚刚阅读了文档。
首先,为了使Bootstrap的浮动标签起作用,需要<input>
和<label>
是兄弟元素,因为浮动标签依赖于:placeholder-shown
伪元素。问题在于,您挂载的Stripe元素不是一个输入,它们实际上是嵌套在iframe中的输入,因此要使Bootstrap的浮动标签正常工作,需要进行一些调整。
其次,您提到了Stripe API文档中说可以使用{ labels: 'floating' }
,但经过尝试后发现它只对挂载为一组的元素有效(不确定叫什么名字),其中之一是address
,它有效是因为标签是在iframe内部(我在下面的Stackblitz链接中附上了证明)。然后,为了在挂载的元素上使用标签,我们必须使用此方法。不幸的是,该方法没有使标签注入到iframe内部,它仍然在外部,因此来自外观API的浮动标签不会起作用。
尽管在iframe内部,幸运的是,输入仍然可以更改iframe外部的类(它可以产生StripeElement--focus
、StripeElement--complete
和StripeElement--invalid
),因此我们可以模仿Bootstrap浮动标签的行为,并将其实现到我们的自定义代码中,通过复制Bootstrap的行为。
我能想到的最简单解决方案是添加以下CSS:
...
/* 重置 #custom-inputs 的浮动标签的原始行为 */
#custom-inputs .form-floating > .form-control:focus ~ label,
#custom-inputs .form-floating > .form-control:not(:placeholder-shown) ~ label {
opacity: 1;
transform: scale(1) translateY(0) translateX(0);
}
/* 模仿 #custom-inputs 的Bootstrap浮动标签行为 */
#custom-inputs .form-floating > .form-control.StripeElement--focus ~ label,
#custom-inputs .form-floating > .form-control.StripeElement--complete ~ label,
#custom-inputs .form-floating > .form-control.StripeElement--invalid ~ label {
opacity: 0.8;
transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem);
}
#custom-inputs .StripeElement--focus {
color: #212529;
background-color: #fff;
border-color: #86b7fe;
outline: 0;
box-shadow: 0 0 0 0.25rem rgb(13 110 253 / 25%);
}
...
然后清空占位符(因为我们想使用浮动标签):
...
if (!this.cardNumber) {
this.cardNumber = this.elements.create('cardNumber', {
...this.emptyOptions,
placeholder: '',
});
this.cardNumber.mount('#floatingNumber');
}
if (!this.cardCvc) {
this.cardCvc = this.elements.create('cardCvc', {
...this emptyOptions,
placeholder: '',
});
this.cardCvc.mount('#floatingCvc');
}
if (!this.cardExpiry) {
this.cardExpiry = this.elements.create('cardExpiry', {
...this.emptyOptions,
placeholder: '',
});
this.cardExpiry.mount('#floatingExpiry');
}
...
英文:
I'm not an expert in angular, bootstrap, or stripejs, but I just read the documentations.
Firstly, in order for bootstrap floating labels to work, it requires the <input>
and <label>
to be siblings, because the floating label will work because of :placeholder-shown
pseudo element. The problem here is that your mounted stripe elements aren't an input, they became an input wrapped by an iframe, so bootstrap floating labels won't work without some tweak.
Secondly, you mentioned the stripe API documentation that says that we can use { labels: 'floating' }
, and after trying this, it turns out that it only works for elements that are mounted as a pack (not sure what it's called), one of that elements is address
, and it works because the label is inside the iframe (I attach the proof on the Stackblitz link down below). And then, in order to use a label on a mounted element, we must use this method. Unfortunately, that method didn't make the label injected inside the iframe, it's still outside, so the floating labels from the appearance API won't work.
Despite being inside the iframe, thankfully, the inputs can still change the class outside the iframe (it could give StripeElement--focus
, StripeElement--complete
, and StripeElement--invalid
), so we could just imitate the behavior of the bootstrap floating labels and implement it to our custom code, by copying the bootstrap behavior.
The easiest solution I could think of is by adding this CSS:
...
/* reset the original behavior of the floating labels for #custom-inputs */
#custom-inputs .form-floating > .form-control:focus ~ label,
#custom-inputs .form-floating > .form-control:not(:placeholder-shown) ~ label {
opacity: 1;
transform: scale(1) translateY(0) translateX(0);
}
/* mimic the behavior of bootstrap floating labels for #custom-inputs */
#custom-inputs .form-floating > .form-control.StripeElement--focus ~ label,
#custom-inputs .form-floating > .form-control.StripeElement--complete ~ label,
#custom-inputs .form-floating > .form-control.StripeElement--invalid ~ label {
opacity: 0.8;
transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem);
}
#custom-inputs .StripeElement--focus {
color: #212529;
background-color: #fff;
border-color: #86b7fe;
outline: 0;
box-shadow: 0 0 0 0.25rem rgb(13 110 253 / 25%);
}
...
And then empty the placeholder (because we want to use the floating labels):
...
if (!this.cardNumber) {
this.cardNumber = this.elements.create('cardNumber', {
...this.emptyOptions,
placeholder: '',
});
this.cardNumber.mount('#floatingNumber');
}
if (!this.cardCvc) {
this.cardCvc = this.elements.create('cardCvc', {
...this.emptyOptions,
placeholder: '',
});
this.cardCvc.mount('#floatingCvc');
}
if (!this.cardExpiry) {
this.cardExpiry = this.elements.create('cardExpiry', {
...this.emptyOptions,
placeholder: '',
});
this.cardExpiry.mount('#floatingExpiry');
}
...
答案2
得分: -1
我已经稍微更改了你的代码,将div
替换为input
。你是想这样做吗?
这段代码中,使用input
标签而不是div
标签可以正常工作,因为name
字段使用的是input
,而不是div
标签。
<h5>Working Floating name</h5>
<div class="form-floating mb-3">
<input type="text" class="form-control" id="floatingInput" formControlName="name" placeholder="Brad Pitt">
<label for="floatingInput">Name</label>
</div>
你可以看到,在你尝试使用的样式中,包括:focus
伪类,它不适用于div
标签。
.form-floating > .form-control-plaintext ~ label, .form-floating > .form-control:focus ~ label, .form-floating > .form-control:not(:placeholder-shown) ~ label, .form-floating > .form-select ~ label {
opacity: .65;
transform: scale(.85) translateY(-0.5rem) translateX(0.15rem);
}
div:focus
不起作用
input:focus
起作用
英文:
I have changed your code a little bit, set input instead div. Are you trying to do that?
https://stackblitz.com/edit/angular-kauqxz?file=src%2Ftest%2Fstripe%2Fstripe.component.css,src%2Ftest%2Fstripe%2Fstripe.component.html
it works with a name input, bc for name you have an input
, not a div
tag
<h5>Working Floating name</h5>
<div class="form-floating mb-3">
<input type="text" class="form-control" id="floatingInput" formControlName="name" placeholder="Brad Pitt">
<label for="floatingInput">Name</label>
</div>
here you can see that this style you are trying to use includes :focus
pseudoclass and it doesn't work with div
.form-floating>.form-control-plaintext~label, .form-floating>.form-control:focus~label, .form-floating>.form-control:not(:placeholder-shown)~label, .form-floating>.form-select~label {
opacity: .65;
transform: scale(.85) translateY(-0.5rem) translateX(0.15rem);
}
div:focus
-> it doesn't work
input:focus
-> it works
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论