Skip to content

Instantly share code, notes, and snippets.

@madeinfree
Created September 16, 2018 11:39
Show Gist options
  • Save madeinfree/d694ca0270943c1ba3ed4c95c5639dcb to your computer and use it in GitHub Desktop.
Save madeinfree/d694ca0270943c1ba3ed4c95c5639dcb to your computer and use it in GitHub Desktop.
Rotate Credit Card for Reactjs
.flex {
display: flex;
}
.outer-margin {
margin-left: 30px;
margin-right: 30px;
}
.animation {
transition: all 0.32s ease;
}
.unfocus-color {
color: rgba(255, 255, 255, 0.3);
}
.focus-color {
color: rgba(255, 255, 255, 1);
}
.credit-card__wrapper {
user-select: none;
position: relative;
perspective: 1000;
transform-style: preserve-3d;
}
.credit-card__gray-rotate {
transform-origin: center center;
transform: rotateY(180deg);
}
.credit-card__full-front-rotate {
transform-origin: center center;
transform: rotateY(180deg);
}
.credit-card__full-back-rotate {
transform-origin: center center;
transform: rotateY(0deg);
}
.credit-card__gray {
background: linear-gradient(
45deg,
rgba(40, 52, 59, 1) 0%,
rgba(130, 140, 149, 1) 63%,
rgba(181, 189, 200, 1) 100%
);
width: 290px;
height: 182px;
box-shadow: 0 0 20px rgba(#000, 0.2);
border-radius: 12px;
backface-visibility: hidden;
}
.credit-card {
position: absolute;
top: 0;
z-index: 1;
background: linear-gradient(45deg, #1e5799 0%, #2989d8 63%, #7db9e8 100%);
width: 290px;
height: 182px;
box-shadow: 0 0 20px rgba(#000, 0.2);
border-radius: 12px;
transform-origin: 0 0;
transform: scale(0, 0);
backface-visibility: hidden;
}
.credit-card__full {
position: absolute;
top: 0;
z-index: 1;
background: linear-gradient(45deg, #1e5799 0%, #2989d8 63%, #7db9e8 100%);
width: 290px;
height: 182px;
box-shadow: 0 0 20px rgba(#000, 0.2);
border-radius: 12px;
transform-origin: 0 0;
transform: scale(1, 1);
backface-visibility: hidden;
}
.credit-card__full-back {
position: absolute;
z-index: 1;
top: 0px;
left: 0px;
background: linear-gradient(45deg, #1e5799 0%, #2989d8 63%, #7db9e8 100%);
width: 290px;
height: 182px;
box-shadow: 0 0 20px rgba(#000, 0.2);
border-radius: 12px;
transform: rotateY(-180deg);
backface-visibility: hidden;
}
.credit-card__full-back-line {
width: 290px;
height: 40px;
background-color: black;
margin-top: 20px;
}
.credit-card__full-back-content {
position: relative;
width: 200px;
height: 40px;
margin-top: 10px;
margin-left: 15px;
font-weight: bold;
background-color: white;
}
.credit-card__full-back-content--cvc {
font-family: Consolas, Courier, monospace;
position: absolute;
bottom: 5px;
right: 10px;
z-index: 3;
}
.credit-card__full-back-content--line--1 {
position: absolute;
top: 10px;
width: 200px;
height: 2px;
z-index: 2;
background-color: rgb(255, 224, 166);
}
.credit-card__full-back-content--line--2 {
position: absolute;
top: 20px;
width: 200px;
height: 2px;
z-index: 2;
background-color: rgb(255, 224, 166);
}
.credit-card__full-back-content--line--3 {
position: absolute;
top: 30px;
width: 200px;
height: 2px;
z-index: 2;
background-color: rgb(255, 224, 166);
}
.credit-card__full-back-issue {
font-family: Consolas, Courier, monospace;
text-align: center;
margin-top: 30px;
font-size: 30px;
color: white;
}
.credit-card__issue {
position: relative;
font-family: Consolas, Courier, monospace;
justify-content: space-between;
z-index: 2;
padding-top: 18px;
display: flex;
align-items: center;
}
.credit-card__issue img {
width: 35px;
height: 28px;
border-radius: 5px;
}
.credit-card__issue-title {
color: white;
font-size: 35px;
}
.credit-card__number {
position: relative;
z-index: 2;
font-family: Consolas, Courier, monospace;
justify-content: space-between;
padding-top: 30px;
font-size: 17px;
display: flex;
}
.credit-card__name-date {
position: relative;
z-index: 2;
justify-content: space-between;
padding-top: 30px;
font-size: 17px;
}
.credit-card__input {
outline: none;
border-radius: 3px;
border: 1px solid #ccc;
height: 35px;
width: 230px;
padding-left: 10px;
}
.credit-card__input-number:focus,
.credit-card__input-name:focus,
.credit-card__input-valid-thru:focus,
.credit-card__input-cvc:focus {
border: 1px solid #000;
}
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function CreditCard(props) {
return (
<div className="credit-card__wrapper">
<div
className={`animation credit-card__gray ${
props.cvc !== "" ? "credit-card__gray-rotate" : ""
}`}
>
<div className="flex outer-margin credit-card__issue">
<img src="https://upload.cc/i1/2018/09/16/7IaB1M.png" />
<div className="credit-card__issue-title">VISA</div>
</div>
<div
className={`flex outer-margin credit-card__number ${
props.focus !== "number" ? "unfocus-color" : "focus-color"
}`}
>
<div>
{props.number[0]
? [1, 2, 3, 4]
.map(
(_, index) =>
props.number[0].split("")[index]
? props.number[0][index]
: "·"
)
.join("")
: "····"}
</div>
<div>
{props.number[1]
? [1, 2, 3, 4]
.map(
(_, index) =>
props.number[1].split("")[index]
? props.number[1][index]
: "·"
)
.join("")
: "····"}
</div>
<div>
{props.number[2]
? [1, 2, 3, 4]
.map(
(_, index) =>
props.number[2].split("")[index]
? props.number[2][index]
: "·"
)
.join("")
: "····"}
</div>
<div>
{props.number[3]
? [1, 2, 3, 4]
.map(
(_, index) =>
props.number[3].split("")[index]
? props.number[3][index]
: "·"
)
.join("")
: "····"}
</div>
</div>
<div className={`flex outer-margin credit-card__name-date `}>
<div
className={`${
props.focus !== "name" ? "unfocus-color" : "focus-color"
}`}
>
{props.name || "NAME HERE"}
</div>
<div
className={`${
props.focus !== "valid" ? "unfocus-color" : "focus-color"
}`}
>
{props.validThru[0]
? [1, 2]
.map(
(_, index) =>
props.validThru[0].split("")[index]
? props.validThru[0][index]
: "·"
)
.join("")
: "··"}{" "}
/{" "}
{props.validThru[1]
? [1, 2]
.map(
(_, index) =>
props.validThru[1].split("")[index]
? props.validThru[1][index]
: "·"
)
.join("")
: "··"}{" "}
</div>
</div>
<div
className={`animation ${
props.number[0] === "" ? "credit-card" : "credit-card__full"
}`}
/>
</div>
<div
className={`animation ${
props.cvc !== ""
? "credit-card__full redit-card__full-front-rotate"
: "credit-card__full-back"
}`}
>
<div className="credit-card__full-back-line" />
<div className="credit-card__full-back-content">
<div className="credit-card__full-back-content--cvc">
<b>{props.cvc}</b>
</div>
<div className="credit-card__full-back-content--line--1" />
<div className="credit-card__full-back-content--line--2" />
<div className="credit-card__full-back-content--line--3" />
</div>
<div className="credit-card__full-back-issue">VISA</div>
</div>
</div>
);
}
class App extends React.PureComponent {
constructor() {
super();
this.state = {
isTrue: false,
number: ["", "", "", ""],
name: "",
validThru: ["", ""],
cvc: "",
focus: "date"
};
}
onChangeNumber = number => {
if (number.replace(/ /g, "").length > 16) return;
this.setState(state => ({
number: number.split(" ")
}));
};
onChangeName = name => {
this.setState(state => ({
name
}));
};
onChangeValidThru = validThru => {
if (validThru.replace(/( )|\//g, "").length > 4) return;
this.setState(state => ({
validThru: validThru.split(" / ")
}));
};
onChangeCVC = cvc => {
if (cvc.length > 3) return;
this.setState(state => ({
cvc
}));
};
onChangeFocus = name => {
this.setState(state => ({
focus: name
}));
};
render() {
return (
<div className="App">
<CreditCard
number={this.state.number}
name={this.state.name}
validThru={this.state.validThru}
cvc={this.state.cvc}
focus={this.state.focus}
/>
<div>
<h2>Number</h2>
<div>
<input
className="animation credit-card__input credit-card__input-number"
placeholder="4211 4211 4211 4211"
value={this.state.number.reduce((curr, next, index, total) => {
if (next !== "" && next.length >= 4 && index !== 3) {
if (total[index + 1] === "") return curr + next;
return curr + next + " ";
}
return curr + next;
}, "")}
autoFocus={true}
onChange={e => this.onChangeNumber(e.currentTarget.value)}
onFocus={() => this.onChangeFocus("number")}
type="text"
/>
</div>
<h2>Name</h2>
<input
className="animation credit-card__input credit-card__input-name"
placeholder="Name here"
value={this.state.name}
onChange={e => this.onChangeName(e.currentTarget.value)}
onFocus={() => this.onChangeFocus("name")}
type="text"
/>
<h2>Valid Thru</h2>
<input
className="animation credit-card__input credit-card__input-valid-thru"
placeholder="Valid Thru"
value={this.state.validThru.reduce((curr, next, index, total) => {
if (next !== "" && index === 0 && next.length === 2) {
if (total[index + 1] === "")
return curr + next.replace(/( )|\//g, "");
return curr + next + " / ";
}
return curr + next;
}, "")}
onChange={e => this.onChangeValidThru(e.currentTarget.value)}
onFocus={() => this.onChangeFocus("valid")}
type="text"
/>
<h2>CVC</h2>
<input
className="animation credit-card__input credit-card__input-cvc"
placeholder="CVC"
value={this.state.cvc}
onChange={e => this.onChangeCVC(e.currentTarget.value)}
onFocus={() => this.onChangeFocus("cvc")}
type="text"
/>
</div>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment