• 개발
  • 22nd September 2026
스크롤바 숨기던 세 줄을 scrollbar-width 한 줄로 — 단, 표준 속성을 쓰는 순간 ::-webkit-scrollbar 는 전부 꺼진다

가로로 흐르는 탭 줄이나 칩 목록에서 스크롤바를 숨기고 싶을 때, 채팅창 옆의 두꺼운 회색 스크롤바를 얇고 옅은 것으로 바꾸고 싶을 때, 지금까지는 이렇게 썼다. .tabs::-webkit-scrollbar { display: none; } /* Chrome·Safari */ .tabs { -ms-overflow-style: none; } /* 옛 Edge·IE */ .tabs { scrollbar-width: none; } /* Firefox */ 세 줄이 전부 같은 일을 한다. ::-webkit-scrollbar 는 표준이 아니라 WebKit 이 2009...

Read More
  • 개발
  • 21st September 2026
Bootstrap 의 .was-validated 스크립트를 지우기 — :has() 와 :user-invalid 로 감싼 박스·라벨·오류 문구까지 CSS 로

폼 검증 표시는 대개 이런 구조로 되어 있다. 입력칸이 틀리면 입력칸 테두리만 빨개지는 게 아니라, 그걸 감싼 박스에 배경이 깔리고, 라벨 색이 바뀌고, 아래에 숨어 있던 오류 문구가 나타난다. 브라우저는 input:invalid 로 입력칸 자신은 골라 줬지만 그걸 감싼 div 나 옆에 있는 label 은 고를 방법이 없었다. CSS 선택자는 아래로만 내려가지 위로는 못 올라갔기 때문이다. 그래서 검증 스타일은 JS 몫이었다. Bootstrap 은...

Read More
  • 개발
  • 21st September 2026
'ZZ' 다음은 'AAA' — $s++ 대신 PHP 8.3 str_increment(), 그리고 0 으로 시작하면 못 내리는 str_decrement()

주문번호, 시리얼, 자산 태그처럼 "다음 번호"를 만들어야 하는 값 중에는 숫자만으로 안 되는 것이 많다. SKU001 의 다음은 SKU002 고, 엑셀 열 이름 Z 의 다음은 AA 다. PHP 에서는 오래전부터 $s++ 가 이걸 해 줬다. 'ABC' 에 ++ 를 하면 'ABD' 가 되고 'ZZ' 는 'AAA' 가 된다. Perl 에서 넘어온 동작이다. 문제는 이 연산자가 문자열마다 다르게 구는 데 있다. '9'++ 는 문자열 '10' 이 아니라 정수 10 이 된다. '5.0'++ 는 실...

Read More
  • 개발
  • 18th September 2026
마지막 항목 앞에 "및" 을 붙이던 코드 — PHP 8.5 IntlListFormatter 로 한 줄, 그리고 한국어에서 남는 일

이름이나 항목을 여러 개 나열해 보여주는 화면은 어디에나 있다. 결재선의 결재자, 회의 참석 부서, 글에 붙은 태그, 파일을 공유한 사람들. 배열을 implode(', ', $items) 로 붙이면 "기획팀, 개발팀, 디자인팀" 이 나오는데, 문장 안에 넣으려면 마지막 항목 앞에 "및" 이나 "and" 를 넣어야 한다. 이걸 손으로 하는 코드가 대개 이런 모양이다. $last = array_pop($items); $text = $items ? implode(', ', $items) . ' 및 ' ....

Read More
  • 개발
  • 11th September 2026
다크 모드 색을 미디어쿼리 두 벌로 쓰던 것을 한 줄로 — CSS light-dark()

다크 모드를 지원하는 CSS는 대개 이런 모양이다. 색마다 변수를 만들고, 미디어쿼리 안에서 같은 변수를 다시 선언한다. :root { --bg: #ffffff; --ink: #1a1a1a; --line: #e0e0e0; --muted: #6b7280; } @media (prefers-color-scheme: dark) { :root { --bg: #14171a; --ink: #f2f2f2; --line: #2c3136; --muted: #9aa4b2; } } 동작은 한다. 대신 변수 목록을 두 벌 관리하게 된다. 색을 하나 추가하면 두 곳에 써야 하고, 한쪽...

Read More
  • 개발
  • 9th September 2026
화면 밖 목록의 렌더를 건너뛴다 — content-visibility 로 레이아웃 속도를 비약적으로 끌어올리기

목록 화면에 항목이 수천 개 있다. 사용자 화면에 실제로 보이는 것은 열 개쯤이다. 그런데 브라우저는 보이지 않는 나머지까지 전부 레이아웃하고 페인트한다. 각 항목의 높이를 계산하고, 문서 전체 높이를 구하고, 스크롤바 길이를 정한다. 이 낭비를 줄이는 방법은 오랫동안 자바스크립트였다. 화면에 보이는 만큼만 DOM에 넣고 스크롤에 따라 갈아 끼우는 가상 스크롤이다. 잘 동작하지만 직접 구현하면 스크롤 위치 복원, 키...

Read More
  • 개발
  • 9th September 2026
PHP 8.6은 세션 쿠키에 HttpOnly·SameSite=Lax를 붙인다 — 11월 19일 전에 확인할 세 가지

PHP 8.6이 2026년 11월 19일에 나온다. 세션 확장의 ini 기본값 셋이 바뀐다. 코드를 한 줄도 고치지 않아도 세션 쿠키에 붙는 속성이 달라진다. 같은 코드에 같은 요청을 보내고 응답 헤더만 비교하면 이렇다. # PHP 8.5.4 Set-Cookie: PHPSESSID=75586de12bb15eb5…; path=/ # PHP 8.6.0beta2 Set-Cookie: PHPSESSID=d6522d741bd160b6…; path=/; HttpOnly; SameSite=Lax 바뀌는 값은 셋이다. 설정 8.5까지 8.6부터 막는 것 sessio...

Read More
  • 개발
  • 8th September 2026
안에서 밖으로 읽던 함수 중첩을, 위에서 아래로 — PHP 8.5 파이프 연산자 |>

입력값을 다듬는 코드는 대개 이런 모양이 된다. $amount = intval(preg_replace('/[^0-9]/', '', str_replace(',', '', trim($raw)))); 실행은 trim부터다. 그 다음 str_replace, preg_replace, intval 순서로 간다. 그런데 눈은 정반대로 움직인다. 왼쪽 끝의 intval을 먼저 만나고, 괄호를 따라 안쪽으로 파고들어 trim에 닿은 다음, 거기서 다시 밖으로 나오면서 순서를 되짚어야 한다. 그래서 보통은 임시 변수로 푼다. $trim...

Read More
  • 개발
  • 8th September 2026
미디어 쿼리로는 안 되던 것 — @container 로 부모가 정한 값에 반응하기

같은 카드 부품이 본문에도 들어가고, 좁은 사이드바에도 들어가고, 어두운 배너 안에도 들어간다. 자리마다 조금씩 달라야 한다. 사이드바에서는 설명을 감추고, 배너 안에서는 글자를 밝게. 화면 크기로 갈라 볼까 싶지만 그건 답이 아니다. 미디어 쿼리는 화면만 본다. 넓은 데스크톱 화면에서도 사이드바는 여전히 좁고, 같은 화면 안에서 본문에 있는 카드와 사이드바에 있는 카드는 구분되지 않는다. 부품이 알아야 하는 것...

Read More
  • 개발
  • 7th September 2026
text-indent: hanging / each-line — padding-left + 음수 text-indent 트릭을 걷어내기

참고문헌 목록, 용어 정의, 시, 대본, 주소. 첫 줄은 왼쪽 끝에 붙고 둘째 줄부터 들여쓰는 내어쓰기(hanging indent)가 필요한 자리는 많다. 그리고 CSS에는 오랫동안 이걸 바로 말하는 문법이 없었다. 대신 모두가 같은 트릭을 썼다. .ref { padding-left: 2em; text-indent: -2em; } 블록 전체를 2em 밀어 넣고, 첫 줄만 2em 도로 당긴다. 결과는 내어쓰기처럼 보인다. 20년 넘게 쓰인 트릭이고 지금도 검색하면 이게 나온다. ...

Read More