[TIL] 211215

Lee Syongยท2021๋…„ 12์›” 15์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
119/204
post-thumbnail

๐Ÿ“ ์˜ค๋Š˜ ํ•œ ๊ฒƒ

  1. ํŒŒ์ผ input CSS ์Šคํƒ€์ผ๋ง

  2. ํ‚ค๋ณด๋“œ ์ ‘๊ทผ์„ฑ - focus-visible

  3. input์˜ change ์ด๋ฒคํŠธ ์„ ํƒํ•œ ํŒŒ์ผ ์ด๋ฆ„ ๋ณด์—ฌ์ฃผ๊ธฐ

  4. ๋ฒ„๊ทธ ์ˆ˜์ •


๐Ÿ“š ๋ฐฐ์šด ๊ฒƒ

1. webassembly video transcode

1) input[type="file"] CSS ์Šคํƒ€์ผ๋ง

input[type="file"]์„ ๋ณด์ด์ง€ ์•Š๊ฒŒ ์ˆจ๊ฒผ๋‹ค.
ํŒŒ์ผ ์ด๋ฆ„์„ ๋ณด์—ฌ์ค„ input์„ readOnly๋กœ ๋งŒ๋“ค์—ˆ๋‹ค.
label์— fontawesome icon์„ ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค.

Styling an input type="file" button ์ฐธ๊ณ 

//- edit-profile.pug

form(method="POST", enctype="multipart/form-data")
  div.file-upload
    input(value="Avatar", readOnly)#avatar__fileName.file-upload__fileName
    label(for="avatar")
      i.fas.fa-file-import
      input(name="avatar", type="file", accept="image/*", id="avatar")
// form.scss

.file-upload {
  display: flex;
  justify-content: space-between;
  font-size: $font-small;
  border: 1px solid $light-grey;
  border-radius: 4px;
  margin: 2px 0;
  input[type="file"] {
    position: absolute;
    left: -99999rem;
    overflow: hidden;
  }
  .file-upload__fileName {
    width: 80%;
    border-style: none;
    background-color: transparent;
    color: $grey;
  }
  .fas.fa-file-import {
    color: white;
    padding: 0 10px;
    line-height: 44px;
    cursor: pointer;
  }
}

2) focus-visible

button๊ณผ input์„ ๋งˆ์šฐ์Šค๋กœ ํด๋ฆญํ–ˆ์„ ๋•Œ ๋‚˜ํƒ€๋‚˜๋Š” outline์„ ์—†์• ๊ณ ์ž ํ•œ๋‹ค.
๊ทธ๋Ÿฐ๋ฐ ์ด๋ฅผ ๋ฌดํ„ฑ๋Œ€๊ณ  ์—†์• ๋ฉด ํ•ด๋‹น ์š”์†Œ์— ํ‚ค๋ณด๋“œ๋กœ๋Š” ์ ‘๊ทผํ•  ์ˆ˜ ์—†๊ฒŒ ๋œ๋‹ค.
๋”ฐ๋ผ์„œ, ๋งˆ์šฐ์Šค๋กœ ํด๋ฆญํ–ˆ์„ ๋•Œ๋งŒ outline์„ ์—†์• ๊ณ , ํ‚ค๋ณด๋“œ๋กœ ์ ‘๊ทผ ์‹œ์—๋Š” focus ๋˜๋„๋ก ์ฆ‰ outline์ด ๋‚˜ํƒ€๋‚˜๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.

button์˜ ๊ฒฝ์šฐ focus-visible๋กœ ํ•ด๊ฒฐ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

// styles.css

button {
  cursor: pointer;
  border-style: none;
}

// ํ‚ค๋ณด๋“œ๋กœ ์ ‘๊ทผ ์‹œ
button:focus-visible {
  outline: $blue solid 1px;
}

// ๋งˆ์šฐ์Šค๋กœ ์ ‘๊ทผ ์‹œ
button:focus:not(:focus-visible) {
  outline: none;
}

๊ทธ๋Ÿฌ๋‚˜, input์€ focus-visible๋กœ ํ•ด๊ฒฐ์ด ์•ˆ๋œ๋‹ค.
ํ‚ค๋ณด๋“œ ์ž…๋ ฅ์„ ์ง€์›ํ•˜๋Š” ์š”์†Œ๋Š” ๋งˆ์šฐ์Šค๋กœ ํด๋ฆญํ•ด๋„ :focus-visible์ด ์ ์šฉ๋˜์–ด ์œ„์ฒ˜๋Ÿผ ์ž‘์„ฑํ•˜๋ฉด ํ‚ค๋ณด๋“œ์™€ ๋งˆ์šฐ์Šค๋กœ ํด๋ฆญํ•  ๋•Œ ๋ชจ๋‘ ์—ฌ์ „ํžˆ outline์ด ๋‚˜ํƒ€๋‚œ๋‹ค.

๋‹ค๋งŒ, video player์˜ ๋ณผ๋ฅจ ๋ฐ”์™€ ํƒ€์ž„๋ผ์ธ์€ ํ‚ค๋ณด๋“œ ์ž…๋ ฅ์„ ์ง€์›ํ•˜์ง€ ์•Š๋Š” input[type="range"]์ด๊ธฐ ๋•Œ๋ฌธ์— :not(:focus-visible)์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

3) button / input ํ…์ŠคํŠธ ์ˆ˜์ง ์ค‘์•™ ์ •๋ ฌ

Vertical text alignment in buttons and inputs

ํ…์ŠคํŠธ๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” button ํ˜น์€ input์˜ ์œ„, ์•„๋ž˜ padding์„ ์ œ๊ฑฐํ•˜๊ณ , line-height๋ฅผ button ํ˜น์€ input์˜ height ๊ฐ’๊ณผ ๋™์ผํ•˜๊ฒŒ ์„ค์ •ํ•œ๋‹ค.

4) ์„ ํƒํ•œ ํŒŒ์ผ ์ด๋ฆ„ ๋ณด์—ฌ์ฃผ๊ธฐ

(1) fileName.js ํŒŒ์ผ ๋งŒ๋“ค๊ณ  ์—ฐ๊ฒฐํ•˜๊ธฐ

client ํด๋”์— fileName.js ํŒŒ์ผ์„ ๋งŒ๋“  ํ›„ webpack.config.json ํŒŒ์ผ์„ ์ˆ˜์ •ํ–ˆ๋‹ค.
upload.pug์™€ edit-profile.pug ํŒŒ์ผ์—์„œ script๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค.
webpack์„ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋ฉด assets ํด๋”์— fileName.js ํŒŒ์ผ์ด ์ถ”๊ฐ€๋œ๋‹ค.

(2) input์˜ change ์ด๋ฒคํŠธ

MDN - ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํŒŒ์ผ ์‚ฌ์šฉํ•˜๊ธฐ ๐Ÿ”ฅ
MDN - HTMLElement: change event
Display file name in page after selecting file in file input ์ฐธ๊ณ 

event.srcElement๋Š” ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€์‹  event.target์„ ์‚ฌ์šฉํ–ˆ๋‹ค.
event.target.files๋Š” ํŒŒ์ผ๋“ค์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๋ฐฐ์—ด์ด๋‹ค.
๋ฐฐ์—ด์˜ ์š”์†Œ์ธ ๊ฐ๊ฐ์˜ ํŒŒ์ผ์€ ๊ฐ์ฒด๋กœ์„œ name, size, type ์†์„ฑ์„ ๊ฐ€์ง„๋‹ค.
๋”ฐ๋ผ์„œ, event.target.files[0].name์„ ํ†ตํ•ด ํŒŒ์ผ ์ด๋ฆ„์„ ์–ป์–ด์˜จ ํ›„ ์ด๋ฅผ ํŒŒ์ผ ์ด๋ฆ„์„ ๋ณด์—ฌ์ค„ input์˜ value ๊ฐ’์— ํ• ๋‹นํ•œ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ฒ˜์Œ์— cannot read property 'addeventlistener' of null ์—๋Ÿฌ๊ฐ€ ๋–ด๋‹ค.
ํ”„๋กœํ•„ ์ˆ˜์ • ํŽ˜์ด์ง€๋กœ ๊ฐ€๋ฉด videoInput์„ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๊ณ  ๋œจ๊ณ , ๋น„๋””์˜ค ์—…๋กœ๋“œ ํŽ˜์ด์ง€๋กœ ๊ฐ€๋ฉด avatarInput์„ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๊ณ  ๋–ด๋‹ค.
script ํƒœ๊ทธ์— defer ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์ด๋ฅผ head ์•ˆ์œผ๋กœ ์˜ฎ๊ฒจ๋„ ํ•ด๊ฒฐ๋˜์ง€ ์•Š์•˜๋‹ค.
์•„์˜ˆ ํ•ด๋‹น ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ๋ฐ›์•„์˜จ ๊ฒƒ์ด ํ™•์‹คํžˆ ํ™•์ธ๋˜๋ฉด ํ•ด๋‹น ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก if ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

// fileName.js
const avatarInput = document.getElementById("avatar");
const videoInput = document.getElementById("video");
const thumbInput = document.getElementById("thumb");
const avatarFileName = document.getElementById("avatar__fileName");
const videoFileName = document.getElementById("video__fileName");
const thumbFileName = document.getElementById("thumb__fileName");

if (avatarInput) {
  const showAvatarFileName = (event) => {
    avatarFileName.value = event.target.files[0].name;
  };
  avatarInput.addEventListener("change", showAvatarFileName);
}

if (videoInput) {
  const showVideoFileName = (event) => {
    videoFileName.value = event.target.files[0].name;
  };
  videoInput.addEventListener("change", showVideoFileName);
}

if (thumbInput) {
  const showThumbFileName = (event) => {
    thumbFileName.value = event.target.files[0].name;
  };
  thumbInput.addEventListener("change", showThumbFileName);
}

2. ๊ทธ ๋ฐ–์˜ ๋ฒ„๊ทธ ์ˆ˜์ •

์˜๋„ํ•œ ๋Œ€๋กœ ๋ณด์ด์ง€ ์•Š๋Š” ๋ถ€๋ถ„๋“ค์„ ๋ฐœ๊ฒฌํ•ด์„œ ๋‹ค์‹œ ์ˆ˜์ •์„ ํ–ˆ๋‹ค.

1) ๋ณผ๋ฅจ ๋ฐ” ์กฐ์ ˆ์— ๋”ฐ๋ฅธ ๋ณผ๋ฅจ ์•„์ด์ฝ˜ ๋ณ€๊ฒฝ

๋ณผ๋ฅจ ๋ฐ”๋ฅผ ์›€์ง์—ฌ ์Œ์†Œ๊ฑฐ ์ƒํƒœ์—์„œ(video.muted) ๋ณผ๋ฅจ ์—… ์ƒํƒœ๋กœ ๋งŒ๋“ค๋ฉด, ์Œ์†Œ๊ฑฐ ์•„์ด์ฝ˜์ด ๋ณผ๋ฅจ ์—… ์•„์ด์ฝ˜์œผ๋กœ ๋ฐ”๋€Œ๋„๋ก ํ–ˆ๋‹ค.
๋ณผ๋ฅจ ๋ฐ”๋ฅผ ์›€์ง์—ฌ ๋ณผ๋ฅจ ์—… ์ƒํƒœ์—์„œ ์Œ์†Œ๊ฑฐ ์ƒํƒœ๋กœ ๋งŒ๋“ค๋ฉด(value === "0"), ๋ณผ๋ฅจ ์—… ์•„์ด์ฝ˜์ด ์Œ์†Œ๊ฑฐ ์•„์ด์ฝ˜์œผ๋กœ ๋ฐ”๋€Œ๋„๋ก ํ–ˆ๋‹ค.

// videoPlayer.js
const handleVolumeChange = (event) => {
  const {
    target: { value },
  } = event;
  if (video.muted) {
    video.muted = false;
    muteBtn.innerHTML = "<i class='fas fa-volume-up'></i>";
  }
  if (value === "0") {
    video.muted = true;
    muteBtn.innerHTML = "<i class='fas fa-volume-mute'></i>";
  }
  volumeValue = value;
  video.volume = volumeValue;
};

2) :hover์™€ :active์— :not([disabled]) ์ถ”๊ฐ€

๋‹ค์šด๋กœ๋“œ๋ฅผ ์‹œ์ž‘ํ•ด์„œ ์™„๋ฃŒํ•˜๊ธฐ ์ „๊นŒ์ง€ ๋‹ค์šด๋กœ๋“œ ๋ฒ„ํŠผ์„ ๋น„ํ™œ์„ฑํ™”(disabled) ํ–ˆ๋‹ค.
์ด๋กœ ์ธํ•ด ๋‹ค์šด๋กœ๋“œ ๋ฒ„ํŠผ์ด ๋ˆŒ๋ฆฌ์ง€๋Š” ์•Š์ง€๋งŒ :hover์™€ :active์— ์„ค์ •ํ•œ transition ๊ฐ’๋“ค๋กœ ์ธํ•ด ๋ฒ„ํŠผ ์œ„์— ๋งˆ์šฐ์Šค๋ฅผ ๊ฐ€์ ธ๊ฐ”์„ ๋•Œ ํšจ๊ณผ๊ฐ€ ์ƒ๊ธด๋‹ค.
์ด๋ฅผ ๋ง‰๊ธฐ ์œ„ํ•ด :not([disabled])๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

// upload.scss

&:hover:not([disabled]) {
  background-color: $red;
  color: white;
}
&:active:not([disabled]) {
  opacity: 0.8;
}

3) ๋น„๋””์˜ค ํ”Œ๋ ˆ์ด์–ด CSS ์ˆ˜์ •

ํฐ์ƒ‰ ์•„์ด์ฝ˜์— ํˆฌ๋ช… ๋ฐฐ๊ฒฝ์„ ์‚ฌ์šฉํ•˜๋‹ˆ๊นŒ ํฐ์ƒ‰ ์˜์ƒ์—์„œ ๋น„๋””์˜ค ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์•ˆ ๋ณด์—ฌ์„œ ๋ฐฐ๊ฒฝ ์ƒ‰์„ ๋ฐ”๊ฟจ๋‹ค.


โœจ ๋‚ด์ผ ํ•  ๊ฒƒ

  1. flash message
profile
๋Šฅ๋™์ ์œผ๋กœ ์‚ด์ž, ํ–‰๋ณตํ•˜๊ฒŒ๐Ÿ˜

0๊ฐœ์˜ ๋Œ“๊ธ€