├── img
├── thumb.png
├── logos
│ ├── visa.png
│ └── mastercard.png
├── chip-tarjeta.png
└── bg-tarjeta
│ ├── bg-tarjeta-01.jpg
│ ├── bg-tarjeta-02.jpg
│ └── bg-tarjeta-03.jpg
├── README.md
├── index.html
├── js
└── main.js
└── css
└── estilos.css
/img/thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/falconmasters/formulario-tarjeta-credito-3d/HEAD/img/thumb.png
--------------------------------------------------------------------------------
/img/logos/visa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/falconmasters/formulario-tarjeta-credito-3d/HEAD/img/logos/visa.png
--------------------------------------------------------------------------------
/img/chip-tarjeta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/falconmasters/formulario-tarjeta-credito-3d/HEAD/img/chip-tarjeta.png
--------------------------------------------------------------------------------
/img/logos/mastercard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/falconmasters/formulario-tarjeta-credito-3d/HEAD/img/logos/mastercard.png
--------------------------------------------------------------------------------
/img/bg-tarjeta/bg-tarjeta-01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/falconmasters/formulario-tarjeta-credito-3d/HEAD/img/bg-tarjeta/bg-tarjeta-01.jpg
--------------------------------------------------------------------------------
/img/bg-tarjeta/bg-tarjeta-02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/falconmasters/formulario-tarjeta-credito-3d/HEAD/img/bg-tarjeta/bg-tarjeta-02.jpg
--------------------------------------------------------------------------------
/img/bg-tarjeta/bg-tarjeta-03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/falconmasters/formulario-tarjeta-credito-3d/HEAD/img/bg-tarjeta/bg-tarjeta-03.jpg
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Taller de Diseño Web: Formulario Dinámico para Tarjeta de Crédito | HTML, CSS y Javascript
2 | ### [Tutorial: https://youtu.be/7bciaLTTr7s](https://youtu.be/7bciaLTTr7s)
3 |
4 | 
5 |
6 | Por: [FalconMasters](http://www.falconmasters.com)
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Formulario de Tarjeta de Crédito Dinámico
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |

21 |
22 |
23 |
Número Tarjeta
24 |
#### #### #### ####
25 |
26 |
27 |
28 |
Nombre Tarjeta
29 |
Jhon Doe
30 |
31 |
32 |
33 |
Expiracion
34 |
MM / AA
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusamus exercitationem, voluptates illo.
53 |
www.tubanco.com
54 |
55 |
56 |
57 |
58 |
59 |
62 |
63 |
64 |
65 |
100 |
101 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/js/main.js:
--------------------------------------------------------------------------------
1 | const tarjeta = document.querySelector('#tarjeta'),
2 | btnAbrirFormulario = document.querySelector('#btn-abrir-formulario'),
3 | formulario = document.querySelector('#formulario-tarjeta'),
4 | numeroTarjeta = document.querySelector('#tarjeta .numero'),
5 | nombreTarjeta = document.querySelector('#tarjeta .nombre'),
6 | logoMarca = document.querySelector('#logo-marca'),
7 | firma = document.querySelector('#tarjeta .firma p'),
8 | mesExpiracion = document.querySelector('#tarjeta .mes'),
9 | yearExpiracion = document.querySelector('#tarjeta .year');
10 | ccv = document.querySelector('#tarjeta .ccv');
11 |
12 | // * Volteamos la tarjeta para mostrar el frente.
13 | const mostrarFrente = () => {
14 | if(tarjeta.classList.contains('active')){
15 | tarjeta.classList.remove('active');
16 | }
17 | }
18 |
19 | // * Rotacion de la tarjeta
20 | tarjeta.addEventListener('click', () => {
21 | tarjeta.classList.toggle('active');
22 | });
23 |
24 | // * Boton de abrir formulario
25 | btnAbrirFormulario.addEventListener('click', () => {
26 | btnAbrirFormulario.classList.toggle('active');
27 | formulario.classList.toggle('active');
28 | });
29 |
30 | // * Select del mes generado dinamicamente.
31 | for(let i = 1; i <= 12; i++){
32 | let opcion = document.createElement('option');
33 | opcion.value = i;
34 | opcion.innerText = i;
35 | formulario.selectMes.appendChild(opcion);
36 | }
37 |
38 | // * Select del año generado dinamicamente.
39 | const yearActual = new Date().getFullYear();
40 | for(let i = yearActual; i <= yearActual + 8; i++){
41 | let opcion = document.createElement('option');
42 | opcion.value = i;
43 | opcion.innerText = i;
44 | formulario.selectYear.appendChild(opcion);
45 | }
46 |
47 | // * Input numero de tarjeta
48 | formulario.inputNumero.addEventListener('keyup', (e) => {
49 | let valorInput = e.target.value;
50 |
51 | formulario.inputNumero.value = valorInput
52 | // Eliminamos espacios en blanco
53 | .replace(/\s/g, '')
54 | // Eliminar las letras
55 | .replace(/\D/g, '')
56 | // Ponemos espacio cada cuatro numeros
57 | .replace(/([0-9]{4})/g, '$1 ')
58 | // Elimina el ultimo espaciado
59 | .trim();
60 |
61 | numeroTarjeta.textContent = valorInput;
62 |
63 | if(valorInput == ''){
64 | numeroTarjeta.textContent = '#### #### #### ####';
65 |
66 | logoMarca.innerHTML = '';
67 | }
68 |
69 | if(valorInput[0] == 4){
70 | logoMarca.innerHTML = '';
71 | const imagen = document.createElement('img');
72 | imagen.src = 'img/logos/visa.png';
73 | logoMarca.appendChild(imagen);
74 | } else if(valorInput[0] == 5){
75 | logoMarca.innerHTML = '';
76 | const imagen = document.createElement('img');
77 | imagen.src = 'img/logos/mastercard.png';
78 | logoMarca.appendChild(imagen);
79 | }
80 |
81 | // Volteamos la tarjeta para que el usuario vea el frente.
82 | mostrarFrente();
83 | });
84 |
85 | // * Input nombre de tarjeta
86 | formulario.inputNombre.addEventListener('keyup', (e) => {
87 | let valorInput = e.target.value;
88 |
89 | formulario.inputNombre.value = valorInput.replace(/[0-9]/g, '');
90 | nombreTarjeta.textContent = valorInput;
91 | firma.textContent = valorInput;
92 |
93 | if(valorInput == ''){
94 | nombreTarjeta.textContent = 'Jhon Doe';
95 | }
96 |
97 | mostrarFrente();
98 | });
99 |
100 | // * Select mes
101 | formulario.selectMes.addEventListener('change', (e) => {
102 | mesExpiracion.textContent = e.target.value;
103 | mostrarFrente();
104 | });
105 |
106 | // * Select Año
107 | formulario.selectYear.addEventListener('change', (e) => {
108 | yearExpiracion.textContent = e.target.value.slice(2);
109 | mostrarFrente();
110 | });
111 |
112 | // * CCV
113 | formulario.inputCCV.addEventListener('keyup', () => {
114 | if(!tarjeta.classList.contains('active')){
115 | tarjeta.classList.toggle('active');
116 | }
117 |
118 | formulario.inputCCV.value = formulario.inputCCV.value
119 | // Eliminar los espacios
120 | .replace(/\s/g, '')
121 | // Eliminar las letras
122 | .replace(/\D/g, '');
123 |
124 | ccv.textContent = formulario.inputCCV.value;
125 | });
--------------------------------------------------------------------------------
/css/estilos.css:
--------------------------------------------------------------------------------
1 | * {
2 | padding: 0;
3 | margin: 0;
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | background: #ddeefc;
9 | font-family: 'Lato', sans-serif;
10 | }
11 |
12 | .contenedor {
13 | width: 90%;
14 | max-width: 1000px;
15 | padding: 40px 20px;
16 | margin: auto;
17 | display: flex;
18 | flex-direction: column;
19 | align-items: center;
20 | }
21 |
22 | /* ---------- Estilos Generales de las Tarjetas ----------*/
23 | .tarjeta {
24 | width: 100%;
25 | max-width: 550px;
26 | position: relative;
27 | color: #fff;
28 | transition: .3s ease all;
29 | transform: rotateY(0deg);
30 | transform-style: preserve-3d;
31 | cursor: pointer;
32 | z-index: 2;
33 | }
34 |
35 | .tarjeta.active {
36 | transform: rotateY(180deg);
37 | }
38 |
39 | .tarjeta > div {
40 | padding: 30px;
41 | border-radius: 15px;
42 | min-height: 315px;
43 | display: flex;
44 | flex-direction: column;
45 | justify-content: space-between;
46 | box-shadow: 0 10px 10px 0 rgba(90,116,148,0.3);
47 | }
48 |
49 | /* ---------- Tarjeta Delantera ----------*/
50 |
51 | .tarjeta .delantera {
52 | width: 100%;
53 | background: url(../img/bg-tarjeta/bg-tarjeta-02.jpg);
54 | background-size: cover;
55 | }
56 |
57 | .delantera .logo-marca {
58 | text-align: right;
59 | min-height: 50px;
60 | }
61 |
62 | .delantera .logo-marca img {
63 | width: 100%;
64 | height: 100%;
65 | object-fit: cover;
66 | max-width: 80px;
67 | }
68 |
69 | .delantera .chip {
70 | width: 100%;
71 | max-width: 50px;
72 | margin-bottom: 20px;
73 | }
74 |
75 | .delantera .grupo .label {
76 | font-size: 16px;
77 | color: #7d8994;
78 | margin-bottom: 5px;
79 | }
80 |
81 | .delantera .grupo .numero,
82 | .delantera .grupo .nombre,
83 | .delantera .grupo .expiracion {
84 | color: #fff;
85 | font-size: 22px;
86 | text-transform: uppercase;
87 | }
88 |
89 | .delantera .flexbox {
90 | display: flex;
91 | justify-content: space-between;
92 | margin-top: 20px;
93 | }
94 |
95 | /* ---------- Tarjeta Trasera ----------*/
96 | .trasera {
97 | background: url(../img/bg-tarjeta/bg-tarjeta-02.jpg);
98 | background-size: cover;
99 | position: absolute;
100 | top: 0;
101 | transform: rotateY(180deg);
102 | backface-visibility: hidden;
103 | }
104 |
105 | .trasera .barra-magnetica {
106 | height: 40px;
107 | background: #000;
108 | width: 100%;
109 | position: absolute;
110 | top: 30px;
111 | left: 0;
112 | }
113 |
114 | .trasera .datos {
115 | margin-top: 60px;
116 | display: flex;
117 | justify-content: space-between;
118 | }
119 |
120 | .trasera .datos p {
121 | margin-bottom: 5px;
122 | }
123 |
124 | .trasera .datos #firma {
125 | width: 70%;
126 | }
127 |
128 | .trasera .datos #firma .firma {
129 | height: 40px;
130 | background: repeating-linear-gradient(skyblue 0, skyblue 5px, orange 5px, orange 10px);
131 | }
132 |
133 | .trasera .datos #firma .firma p {
134 | line-height: 40px;
135 | font-family: 'Liu Jian Mao Cao', cursive;
136 | color: #000;
137 | font-size: 30px;
138 | padding: 0 10px;
139 | text-transform: capitalize;
140 | }
141 |
142 | .trasera .datos #ccv {
143 | width: 20%;
144 | }
145 |
146 | .trasera .datos #ccv .ccv {
147 | background: #fff;
148 | height: 40px;
149 | color: #000;
150 | padding: 10px;
151 | text-align: center;
152 | }
153 |
154 | .trasera .leyenda {
155 | font-size: 14px;
156 | line-height: 24px;
157 | }
158 |
159 | .trasera .link-banco {
160 | font-size: 14px;
161 | color: #fff;
162 | }
163 |
164 | /* ---------- Contenedor Boton ----------*/
165 | .contenedor-btn .btn-abrir-formulario {
166 | width: 50px;
167 | height: 50px;
168 | font-size: 20px;
169 | line-height: 20px;
170 | background: #2364d2;
171 | color: #fff;
172 | position: relative;
173 | top: -25px;
174 | z-index: 3;
175 | border-radius: 100%;
176 | box-shadow: -5px 4px 8px rgba(24,56,182,0.4);
177 | padding: 5px;
178 | transition: all .2s ease;
179 | border: none;
180 | cursor: pointer;
181 | }
182 |
183 | .contenedor-btn .btn-abrir-formulario:hover {
184 | background: #1850b1;
185 | }
186 |
187 | .contenedor-btn .btn-abrir-formulario.active {
188 | transform: rotate(45deg);
189 | }
190 |
191 | /* ---------- Formulario Tarjeta ----------*/
192 | .formulario-tarjeta {
193 | background: #fff;
194 | width: 100%;
195 | max-width: 700px;
196 | padding: 150px 30px 30px 30px;
197 | border-radius: 10px;
198 | position: relative;
199 | top: -150px;
200 | z-index: 1;
201 | clip-path: polygon(0 0, 100% 0, 100% 0, 0 0);
202 | transition: clip-path .3s ease-out;
203 | }
204 |
205 | .formulario-tarjeta.active {
206 | clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
207 | }
208 |
209 | .formulario-tarjeta label {
210 | display: block;
211 | color: #7d8994;
212 | margin-bottom: 5px;
213 | font-size: 16px;
214 | }
215 |
216 | .formulario-tarjeta input,
217 | .formulario-tarjeta select,
218 | .btn-enviar {
219 | border: 2px solid #CED6E0;
220 | font-size: 18px;
221 | height: 50px;
222 | width: 100%;
223 | padding: 5px 12px;
224 | transition: .3s ease all;
225 | border-radius: 5px;
226 | }
227 |
228 | .formulario-tarjeta input:hover,
229 | .formulario-tarjeta select:hover {
230 | border: 2px solid #93BDED;
231 | }
232 |
233 | .formulario-tarjeta input:focus,
234 | .formulario-tarjeta select:focus {
235 | outline: rgb(4,4,4);
236 | box-shadow: 1px 7px 10px -5px rgba(90,116,148,0.3);
237 | }
238 |
239 | .formulario-tarjeta input {
240 | margin-bottom: 20px;
241 | text-transform: uppercase;
242 | }
243 |
244 | .formulario-tarjeta .flexbox {
245 | display: flex;
246 | justify-content: space-between;
247 | }
248 |
249 | .formulario-tarjeta .expira {
250 | width: 100%;
251 | }
252 |
253 | .formulario-tarjeta .ccv {
254 | min-width: 100px;
255 | }
256 |
257 | .formulario-tarjeta .grupo-select {
258 | width: 100%;
259 | margin-right: 15px;
260 | position: relative;
261 | }
262 |
263 | .formulario-tarjeta select {
264 | -webkit-appearance: none;
265 | }
266 |
267 | .formulario-tarjeta .grupo-select i {
268 | position: absolute;
269 | color: #CED6E0;
270 | top: 18px;
271 | right: 15px;
272 | transition: .3s ease all;
273 | }
274 |
275 | .formulario-tarjeta .grupo-select:hover i {
276 | color: #93bfed;
277 | }
278 |
279 | .formulario-tarjeta .btn-enviar {
280 | border: none;
281 | padding: 10px;
282 | font-size: 22px;
283 | color: #fff;
284 | background: #2364d2;
285 | box-shadow: 2px 2px 10px 0px rgba(0,85,212,0.4);
286 | cursor: pointer;
287 | }
288 |
289 | .formulario-tarjeta .btn-enviar:hover {
290 | background: #1850b1;
291 | }
--------------------------------------------------------------------------------