<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>웹솔루션개발 26년 노하우! 해피CGI의 모든것</title>
    <link>https://happycgi.tistory.com/</link>
    <description>웹솔루션개발 26년 노하우! 해피CGI의 모든것</description>
    <language>ko</language>
    <pubDate>Sat, 27 Jun 2026 16:47:00 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>해피CGI윤실장</managingEditor>
    <image>
      <title>웹솔루션개발 26년 노하우! 해피CGI의 모든것</title>
      <url>https://t1.daumcdn.net/cfile/tistory/2156DC4B580719FD05</url>
      <link>https://happycgi.tistory.com</link>
    </image>
    <item>
      <title>[해피CGI][cgimall] AI 시대 인력 이동의 그래프를 보여주는 사이트 7min.ai/exodus</title>
      <link>https://happycgi.tistory.com/4063</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;209&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lwFyx/dJMcaccwWEB/Cj8uWctRmdSHNEKkcFQMa1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lwFyx/dJMcaccwWEB/Cj8uWctRmdSHNEKkcFQMa1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lwFyx/dJMcaccwWEB/Cj8uWctRmdSHNEKkcFQMa1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlwFyx%2FdJMcaccwWEB%2FCj8uWctRmdSHNEKkcFQMa1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;715&quot; height=&quot;209&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;209&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;상단에 타임라인이 있으며, 기간에 대하 조회가 가능하며,&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Bc1q9/dJMcadPY3PC/lC1SdbkbkLJQJoiwXDJCnk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Bc1q9/dJMcadPY3PC/lC1SdbkbkLJQJoiwXDJCnk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Bc1q9/dJMcadPY3PC/lC1SdbkbkLJQJoiwXDJCnk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBc1q9%2FdJMcadPY3PC%2FlC1SdbkbkLJQJoiwXDJCnk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;715&quot; height=&quot;530&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;530&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;그에 따라 이동 경로가 그래프로 나타납니다.&lt;br /&gt;&lt;br /&gt;앤트로픽 에서 딥마인 등으로 인력이 이동한걸 확인할 수 있습니다.&lt;br /&gt;재미로 AI 시대 인력 이동이 어떻게 이뤄지는지 확인해 보시면 되겠습니다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;&gt;&lt;a href=&quot;https://happycgi.com/program/detail.php?number=18168&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cL9Ddx/dJMcagzdSL8/trx8gox6QH4eWjf7EZ0Mbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcL9Ddx%2FdJMcagzdSL8%2Ftrx8gox6QH4eWjf7EZ0Mbk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;140&quot; height=&quot;40&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>웹프로그램밍 자료실/AI 자료</category>
      <category>CGIMALL</category>
      <category>happycgi</category>
      <category>인력이동</category>
      <category>해피CGI</category>
      <author>해피CGI윤실장</author>
      <guid isPermaLink="true">https://happycgi.tistory.com/4063</guid>
      <comments>https://happycgi.tistory.com/4063#entry4063comment</comments>
      <pubDate>Fri, 26 Jun 2026 09:06:54 +0900</pubDate>
    </item>
    <item>
      <title>[해피CGI][cgimall] Cursor Ver 3 : AI 기반 코드 편집기</title>
      <link>https://happycgi.tistory.com/4062</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;AI 코딩 편집기로 사랑 받고 있는 커서가 버전 3 으로 업데이트 되었습니다.&lt;br /&gt;&lt;br /&gt;버전 3 으로 업데이트 되면서&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;316&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQmrV5/dJMcaa6TxXX/nqpTpVWUdW2afVkMAFzThk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQmrV5/dJMcaa6TxXX/nqpTpVWUdW2afVkMAFzThk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQmrV5/dJMcaa6TxXX/nqpTpVWUdW2afVkMAFzThk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQmrV5%2FdJMcaa6TxXX%2FnqpTpVWUdW2afVkMAFzThk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;663&quot; height=&quot;316&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;316&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;위의 새로운 기능들이 추가 되었습니다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://cursor.com/ko/blog/cursor-3&quot;&gt;https://cursor.com/ko/blog/cursor-3&lt;/a&gt;&lt;a href=&quot;https://cursor.com/ko/blog/cursor-3&quot;&gt;&lt;br /&gt;&lt;br /&gt;자&lt;/a&gt;세한 내용은 위의 링크에서 확인이 가능합니다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmdOxY/dJMcaa6TxXY/sFrDB8iRQKUC2aYuJbXkz1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmdOxY/dJMcaa6TxXY/sFrDB8iRQKUC2aYuJbXkz1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmdOxY/dJMcaa6TxXY/sFrDB8iRQKUC2aYuJbXkz1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmdOxY%2FdJMcaa6TxXY%2FsFrDB8iRQKUC2aYuJbXkz1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;715&quot; height=&quot;400&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;에이전트 중심으로 인터페이스 개선도 이뤄졌습니다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;451&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wPgtc/dJMcacje4Wh/wKQUQdyxXi8iodphJ2FT9k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wPgtc/dJMcacje4Wh/wKQUQdyxXi8iodphJ2FT9k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wPgtc/dJMcacje4Wh/wKQUQdyxXi8iodphJ2FT9k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwPgtc%2FdJMcacje4Wh%2FwKQUQdyxXi8iodphJ2FT9k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;664&quot; height=&quot;451&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;451&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;무료 플랜도 있으니, 제한된 Agent 로 취미용으로 사용해 보시기 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;&gt;&lt;a href=&quot;https://happycgi.com/program/detail.php?number=18167&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJI6qE/dJMcaay2z1U/Eult4ZEkV08lgTR89RLGeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJI6qE%2FdJMcaay2z1U%2FEult4ZEkV08lgTR89RLGeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;140&quot; height=&quot;40&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>웹프로그램밍 자료실/AI 자료</category>
      <category>CGIMALL</category>
      <category>happycgi</category>
      <category>에디터</category>
      <category>편집기</category>
      <category>해피CGI</category>
      <author>해피CGI윤실장</author>
      <guid isPermaLink="true">https://happycgi.tistory.com/4062</guid>
      <comments>https://happycgi.tistory.com/4062#entry4062comment</comments>
      <pubDate>Thu, 25 Jun 2026 09:13:49 +0900</pubDate>
    </item>
    <item>
      <title>[해피CGI][cgimall] AI 캐릭터와 대화하고, 이야기를 만들어가는 차세대 AI 소셜 챗 플랫폼 &amp;ndash; Polybuzz AI</title>
      <link>https://happycgi.tistory.com/4061</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Polybuzz AI는 일반적인 챗봇이 아니라 수천만 개의 AI 캐릭터와 대화하고직접 캐릭터를 만들어 스토리&amp;middot;롤플레이&amp;middot;대화 경험을 즐기는 AI 기반 소셜 인터랙션 플랫폼입니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;527&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xIb0j/dJMcadJabxR/9WTrOSV4NayfUBWlgk9ui0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xIb0j/dJMcadJabxR/9WTrOSV4NayfUBWlgk9ui0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xIb0j/dJMcadJabxR/9WTrOSV4NayfUBWlgk9ui0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxIb0j%2FdJMcadJabxR%2F9WTrOSV4NayfUBWlgk9ui0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;650&quot; height=&quot;527&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;527&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;div&gt;&lt;b&gt;주요 기능&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;1. AI 캐릭터 채팅 (핵심 기능)&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;2. 캐릭터 생성 &amp;amp; 커스터마이징&lt;/div&gt;
&lt;div&gt;3. 롤플레이 &amp;amp; 스토리 진행&lt;/div&gt;
&lt;div&gt;4. 음성 &amp;amp; 이미지 기능&lt;/div&gt;
&lt;div&gt;5. 장기 기억 &amp;amp; 관계 형성&lt;/div&gt;
&lt;div&gt;6. 포인트 &amp;amp; 코인 시스템&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;구독료&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;- 무료 플랜 : 기본 채팅 가능, 일부 캐릭터 사용 가능&lt;/div&gt;
&lt;div&gt;- 유료 플랜 : 월 7 ~ 20달러 : 광고제거, 고급 AI 모델, 장기 기억 등 상위 기능 제공&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;892&quot; data-origin-height=&quot;541&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ljd50/dJMcad3uXXm/o65sKYFTkgdqAKfzp6oCi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ljd50/dJMcad3uXXm/o65sKYFTkgdqAKfzp6oCi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ljd50/dJMcad3uXXm/o65sKYFTkgdqAKfzp6oCi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLjd50%2FdJMcad3uXXm%2Fo65sKYFTkgdqAKfzp6oCi0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;650&quot; height=&quot;541&quot; data-origin-width=&quot;892&quot; data-origin-height=&quot;541&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;1. 캐릭터 기반 몰입감&lt;/div&gt;
&lt;div&gt;2. 자유도 높은 대화&lt;/div&gt;
&lt;div&gt;3. 무료 진입 가능&lt;/div&gt;
&lt;div&gt;4. 커뮤니티 &amp;amp; 캐릭터 생태계&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Polybuzz ai는 업무나 생산성을 높이는 플랫폼은 아니고, AI 캐릭터를 생성해서 대화하고 노는 엔터테인먼트 AI입니다.&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;&gt;&lt;a href=&quot;https://happycgi.com/program/detail.php?number=18166&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdchvJ/dJMcag61KG3/7uYeYb8ff5ymMPXn9UaBm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdchvJ%2FdJMcag61KG3%2F7uYeYb8ff5ymMPXn9UaBm1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;140&quot; height=&quot;40&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>웹프로그램밍 자료실/AI 자료</category>
      <category>CGIMALL</category>
      <category>happycgi</category>
      <category>챗봇</category>
      <category>해피CGI</category>
      <author>해피CGI윤실장</author>
      <guid isPermaLink="true">https://happycgi.tistory.com/4061</guid>
      <comments>https://happycgi.tistory.com/4061#entry4061comment</comments>
      <pubDate>Wed, 24 Jun 2026 09:10:06 +0900</pubDate>
    </item>
    <item>
      <title>[해피CGI][cgimall]&amp;nbsp;실무&amp;nbsp;중심&amp;nbsp;AI&amp;nbsp;서비스&amp;nbsp;Kimi&amp;nbsp;AI</title>
      <link>https://happycgi.tistory.com/4060</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;대용량 문서 처리부터 업무 자동화까지 실무에 바로 쓰는 차세대 AI 플랫폼, Kimi AI&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Qqb5S/dJMcaasflz5/KyrXzL4QE4lb6dbOzArHY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Qqb5S/dJMcaasflz5/KyrXzL4QE4lb6dbOzArHY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Qqb5S/dJMcaasflz5/KyrXzL4QE4lb6dbOzArHY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQqb5S%2FdJMcaasflz5%2FKyrXzL4QE4lb6dbOzArHY1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;650&quot; height=&quot;480&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;div&gt;&lt;b&gt;주요 기능&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;1. 초장문 문서 분석&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;PDF, 계약서, 보고서 등 대용량 문서 처리&lt;/div&gt;
&lt;div&gt;문서 간 비교 및 분석&lt;br /&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;2. 코드 생성 및 개발 지원&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;PHP, Python, JavaScript 등 다양한 언어 지원&lt;/div&gt;
&lt;div&gt;기존 코드 분석 및 개선&lt;/div&gt;
&lt;div&gt;반복 개발 작업 자동화&lt;br /&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;3. 업무 자동화 (AI Agent)&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;자료 조사 &amp;rarr; 정리 &amp;rarr; 결과 생성까지 자동 수행&lt;/div&gt;
&lt;div&gt;반복 업무 최소화&lt;/div&gt;
&lt;div&gt;생산성 극대화&lt;br /&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;4. 콘텐츠 생성&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;상품 설명, 블로그, 마케팅 문구 생성&lt;/div&gt;
&lt;div&gt;대량 콘텐츠 빠른 제작&lt;/div&gt;
&lt;div&gt;일관된 문체 유지&lt;br /&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBJvvC/dJMcaasflz3/E4Vo2uf1dV6Lpybu52mkK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBJvvC/dJMcaasflz3/E4Vo2uf1dV6Lpybu52mkK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBJvvC/dJMcaasflz3/E4Vo2uf1dV6Lpybu52mkK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBJvvC%2FdJMcaasflz3%2FE4Vo2uf1dV6Lpybu52mkK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;448&quot; height=&quot;384&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;384&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;&lt;br /&gt;&lt;b&gt;구독료&lt;/b&gt;&lt;br /&gt;1. 무료 플랜&lt;br /&gt;&lt;br /&gt;2. 유료 플랜 : 10 ~ 30 달러&amp;nbsp;&lt;br /&gt;- 더 긴 문서 처리&lt;br /&gt;- 고성능 모델 사용&lt;br /&gt;- 빠른 응답속도&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;아주 긴문서는 메이저 AI 보다 유리한점은 있다.&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;&gt;&lt;a href=&quot;https://happycgi.com/program/detail.php?number=18165&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l8eWn/dJMcacwOrHJ/Gn0jhzNKa6XPuHrHx4uy91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl8eWn%2FdJMcacwOrHJ%2FGn0jhzNKa6XPuHrHx4uy91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;140&quot; height=&quot;40&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>웹프로그램밍 자료실/AI 자료</category>
      <category>CGIMALL</category>
      <category>happycgi</category>
      <category>문서처리</category>
      <category>업무자동화</category>
      <category>해피CGI</category>
      <author>해피CGI윤실장</author>
      <guid isPermaLink="true">https://happycgi.tistory.com/4060</guid>
      <comments>https://happycgi.tistory.com/4060#entry4060comment</comments>
      <pubDate>Tue, 23 Jun 2026 09:05:32 +0900</pubDate>
    </item>
    <item>
      <title>[해피CGI][cgimall] pencere &amp;ndash; 이미지&amp;middot;동영상&amp;middot;아이프레임 지원 접근성 갤러리 라이트박스</title>
      <link>https://happycgi.tistory.com/4059</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;pencere &amp;ndash; 이미지&amp;middot;동영상&amp;middot;iframe 지원 접근성 갤러리 라이트박스&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ &quot;pencere&quot;는 터키어로 &quot;창문&quot;이라는 뜻입니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;343&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjKQjk/dJMcah5YXyy/i4yDDUXl1ZGxB7zB3Hwm9k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjKQjk/dJMcah5YXyy/i4yDDUXl1ZGxB7zB3Hwm9k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjKQjk/dJMcah5YXyy/i4yDDUXl1ZGxB7zB3Hwm9k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjKQjk%2FdJMcah5YXyy%2Fi4yDDUXl1ZGxB7zB3Hwm9k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;715&quot; height=&quot;343&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;343&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;# 짧은 설명&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;JavaScript/TypeScript 기반의 미디어 뷰어 라이브러리로, 이미지&amp;middot;동영상&amp;middot;iframe&amp;middot;커스텀 HTML 콘텐츠를 반응형 갤러리 라이트박스로 표시합니다. View Transitions API를 활용해 썸네일에서 라이트박스로 부드럽게 전환되는 모핑 효과를 제공하며, 프레임워크에 종속되지 않으면서도 React, Vue, Svelte, Solid, Web Components용 어댑터를 모두 지원합니다.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;# 라이센스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;MIT License&lt;/b&gt; (상업적 이용 가능, 자유로운 수정&amp;middot;배포 가능)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;# 설치방법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;① NPM 설치&lt;/h3&gt;
&lt;pre class=&quot;cmake&quot; style=&quot;background-color: #f5f5f5;&quot;&gt;&lt;code&gt;npm install pencere&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;capnproto&quot; style=&quot;background-color: #f5f5f5;&quot;&gt;&lt;code&gt;import { PencereViewer } from &quot;pencere&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;② CDN 방식&lt;/h3&gt;
&lt;pre class=&quot;&quot; style=&quot;background-color: #f5f5f5;&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;③ JavaScript로 갤러리 생성&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;background-color: #f5f5f5;&quot;&gt;&lt;code&gt;const viewer = new PencereViewer({   items: [     { type: &quot;image&quot;, src: &quot;/photos/coast.jpg&quot;, alt: &quot;Coastal cliffs&quot;, caption: &quot;Pacific Coast&quot; },     { type: &quot;image&quot;, src: &quot;/photos/forest.jpg&quot;, alt: &quot;Redwood forest&quot; },   ],   loop: true,   viewTransition: true,  // 썸네일&amp;rarr;라이트박스 모핑 효과   routing: true,         // URL 해시(#p1, #p2)에 슬라이드 위치 기록 })  document.querySelector('#gallery-trigger')   ?.addEventListener('click', (e) =&amp;gt; viewer.open(0, e.currentTarget))&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;④ HTML 선언적 사용 (bindPencere)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML 마크업만으로 자동 갤러리 그룹화가 가능합니다.&lt;/p&gt;
&lt;pre class=&quot;dust&quot; style=&quot;background-color: #f5f5f5;&quot;&gt;&lt;code&gt;&amp;lt;a href=&quot;/photos/coast.jpg&quot; data-pencere data-gallery=&quot;nature&quot; data-caption=&quot;Pacific Coast&quot;&amp;gt;   &amp;lt;img src=&quot;/photos/coast-thumb.jpg&quot; alt=&quot;Coastal cliffs&quot; /&amp;gt; &amp;lt;/a&amp;gt; &amp;lt;a href=&quot;/photos/forest.jpg&quot; data-pencere data-gallery=&quot;nature&quot; data-caption=&quot;Redwood Forest&quot;&amp;gt;   &amp;lt;img src=&quot;/photos/forest-thumb.jpg&quot; alt=&quot;Redwood forest&quot; /&amp;gt; &amp;lt;/a&amp;gt;  &amp;lt;script type=&quot;module&quot;&amp;gt;   import { bindPencere } from &quot;pencere&quot;   const unbind = bindPencere(&quot;[data-pencere]&quot;) &amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;⑤ 프레임워크별 사용&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;React&lt;/b&gt;: import { useLightbox } from &quot;pencere/react&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Vue&lt;/b&gt;: import { usePencere } from &quot;pencere/vue&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Svelte&lt;/b&gt;: import { pencere } from &quot;pencere/svelte&quot; (use: 디렉티브)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Web Component&lt;/b&gt;: &amp;lt;pencere-lightbox&amp;gt; 커스텀 엘리먼트 등록&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;# 중요 옵션&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;items&lt;/td&gt;
&lt;td&gt;표시할 콘텐츠 배열 (type은 image/video/iframe/html)&lt;/td&gt;
&lt;td&gt;필수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;startIndex&lt;/td&gt;
&lt;td&gt;처음 열 슬라이드 인덱스 (0부터)&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;loop&lt;/td&gt;
&lt;td&gt;마지막&amp;rarr;처음 순환 탐색&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;container&lt;/td&gt;
&lt;td&gt;뷰어를 마운트할 특정 DOM 요소&lt;/td&gt;
&lt;td&gt;body&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;strings / i18n&lt;/td&gt;
&lt;td&gt;UI 문자열 개별 오버라이드 / 전체 번역 함수&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;keyboard&lt;/td&gt;
&lt;td&gt;키 바인딩 재매핑 또는 비활성화&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;image&lt;/td&gt;
&lt;td&gt;생성되는 &amp;lt;img&amp;gt;의 crossOrigin, referrerPolicy 설정&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reducedMotion&lt;/td&gt;
&lt;td&gt;애니메이션 정책 (auto / always / never)&lt;/td&gt;
&lt;td&gt;auto&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useNativeDialog&lt;/td&gt;
&lt;td&gt;네이티브 &amp;lt;dialog&amp;gt; 요소로 렌더링&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lockScroll&lt;/td&gt;
&lt;td&gt;뷰어 열림 중 페이지 스크롤 잠금&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nonce&lt;/td&gt;
&lt;td&gt;CSP nonce (구형 브라우저용 fallback &amp;lt;style&amp;gt;에 적용)&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dir&lt;/td&gt;
&lt;td&gt;텍스트 방향 (ltr / rtl / auto)&lt;/td&gt;
&lt;td&gt;auto&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;haptics&lt;/td&gt;
&lt;td&gt;터치 디바이스 진동 피드백 활성화&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;routing&lt;/td&gt;
&lt;td&gt;URL 해시에 슬라이드 위치 기록 (#p1, #p2&amp;hellip;)&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fullscreen&lt;/td&gt;
&lt;td&gt;전체화면 컨트롤 노출 (iOS Safari는 CSS fallback)&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;viewTransition&lt;/td&gt;
&lt;td&gt;View Transitions API로 썸네일&amp;rarr;뷰어 모핑 활성화&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;renderers&lt;/td&gt;
&lt;td&gt;커스텀 콘텐츠 렌더러 등록 (3D 모델 등)&lt;/td&gt;
&lt;td&gt;[ ]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;옵션명 설명 기본값&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;주요 API 메서드&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;viewer.open(index, thumbnailElement)&lt;/td&gt;
&lt;td&gt;지정 인덱스로 열기 (썸네일 요소를 두번째 인자로 넘기면 모핑 효과 활성화)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;viewer.close()&lt;/td&gt;
&lt;td&gt;뷰어 프로그래밍 방식 닫기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;viewer.next() / viewer.prev()&lt;/td&gt;
&lt;td&gt;다음/이전 슬라이드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;viewer.goTo(index)&lt;/td&gt;
&lt;td&gt;특정 인덱스로 이동&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;viewer.openFromLocation()&lt;/td&gt;
&lt;td&gt;URL 해시 기반으로 해당 슬라이드 열기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;viewer.enterFullscreen() / viewer.toggleFullscreen()&lt;/td&gt;
&lt;td&gt;전체화면 진입 / 토글&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;메서드 설명&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;라이프사이클 이벤트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;willOpen, change, slideLoad, didRender, didNavigate, close (close 시 reason: escape / backdrop / user / api)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;# 특징 및 설명&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;콘텐츠 타입&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이미지, 동영상, iframe, 커스텀 HTML을 단일 라이트박스에서 모두 처리&lt;/li&gt;
&lt;li&gt;커스텀 렌더러 등록 가능 (예: &amp;lt;model-viewer&amp;gt; 같은 3D 모델 웹 컴포넌트)&lt;/li&gt;
&lt;li&gt;&amp;lt;picture&amp;gt; 태그 자동 생성으로 AVIF/WebP 형식 자동 협상 (sources 배열 사용 시)&lt;/li&gt;
&lt;li&gt;srcset, sizes로 반응형 이미지 지원&lt;/li&gt;
&lt;li&gt;ThumbHash&amp;middot;BlurHash 플레이스홀더 크로스페이드&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;모션 &amp;amp; 인터랙션&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;View Transitions API 기반 네이티브 썸네일&amp;rarr;라이트박스 모핑 효과&lt;/li&gt;
&lt;li&gt;핀치 줌, 더블탭 토글, 마우스 휠 줌, 확대 이미지 드래그 팬&lt;/li&gt;
&lt;li&gt;아래로 스와이프해서 닫기 (배경 페이드 효과)&lt;/li&gt;
&lt;li&gt;전체화면 API 지원 (iOS Safari는 CSS 고정 위치 오버레이로 fallback)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;접근성 (WCAG 2.2 AA 완전 준수)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;포커스 관리, 44&amp;times;44px 터치 타겟, 키보드 사용자용 드래그 대체 수단&lt;/li&gt;
&lt;li&gt;IME 안전 키보드 단축키 (한글 등 조합 입력 중에는 단축키 무시)&lt;/li&gt;
&lt;li&gt;prefers-reduced-motion 미디어 쿼리 자동 반응&lt;/li&gt;
&lt;li&gt;14개 언어 내장 번역 (한국어, 일본어, 중국어 간체, 아랍어 등 포함)&lt;/li&gt;
&lt;li&gt;RTL 자동 감지 &amp;rarr; 화살표&amp;middot;스와이프&amp;middot;레이아웃 자동 반전 (아랍어&amp;middot;히브리어)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;라우팅 &amp;amp; 공유&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해시 기반 딥링크: 슬라이드 변경 시 URL fragment(#p1, #p2) 자동 기록&lt;/li&gt;
&lt;li&gt;페이지 로드 시 URL 해시 읽어서 해당 슬라이드 자동 오픈&lt;/li&gt;
&lt;li&gt;브라우저 뒤로가기 버튼이 뷰어를 닫음 (popstate 감지)&lt;/li&gt;
&lt;li&gt;해시 패턴 커스터마이징 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;보안 &amp;amp; 배포 안정성&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Strict CSP 호환: adoptedStyleSheets 사용으로 style-src 우회 (Chrome 73+, Firefox 101+, Safari 16.4+)&lt;/li&gt;
&lt;li&gt;구형 브라우저는 nonce 기반 fallback &amp;lt;style&amp;gt; 지원&lt;/li&gt;
&lt;li&gt;HTML 캡션용 Trusted Types 정책 헬퍼 제공&lt;/li&gt;
&lt;li&gt;SLSA 검증된 npm 릴리스, CDN용 SRI 해시 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테마 &amp;amp; 커스터마이징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 시각 속성을 CSS 커스텀 프로퍼티로 노출 (--pc-bg, --pc-fg, --pc-font, --pc-focus 등)&lt;/li&gt;
&lt;li&gt;어디서든 CSS cascade로 오버라이드 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프레임워크 지원&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프레임워크 무관 코어 + React, Vue, Svelte, Solid, Web Components용 어댑터 별도 제공&lt;/li&gt;
&lt;li&gt;모바일 환경에서 옵션 활성화 시 햅틱 피드백 (Vibration API)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추천 활용처&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포트폴리오 사이트(썸네일 그리드에서 풀해상도 모핑 오버레이), 이커머스 상품 페이지(이미지&amp;middot;동영상&amp;middot;3D 모델을 하나의 라이트박스에), 뉴스&amp;middot;에디토리얼 사이트(외부 URL에서 특정 갤러리 슬라이드로 딥링크).&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고 링크&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GitHub 원본: &lt;a href=&quot;https://github.com/productdevbook/pencere&quot;&gt;https://github.com/productdevbook/pencere&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;라이브 데모: &lt;a href=&quot;https://www.cssscript.com/demo/gallery-lightbox-pencere&quot;&gt;cssscript.com 데모&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;demo/demo.html 을 만들어 두었습니다. (cdn 이용하는 방식)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;&gt;&lt;a href=&quot;https://happycgi.com/program/detail.php?number=18164&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cj2J7p/dJMcah5YXya/G5D6GKiIvzRlfErB4vif9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcj2J7p%2FdJMcah5YXya%2FG5D6GKiIvzRlfErB4vif9K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;140&quot; height=&quot;40&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>웹프로그램밍 자료실/JAVA 자료</category>
      <category>CGIMALL</category>
      <category>happycgi</category>
      <category>갤러리</category>
      <category>동영상</category>
      <category>이미지</category>
      <category>해피CGI</category>
      <author>해피CGI윤실장</author>
      <guid isPermaLink="true">https://happycgi.tistory.com/4059</guid>
      <comments>https://happycgi.tistory.com/4059#entry4059comment</comments>
      <pubDate>Mon, 22 Jun 2026 09:14:21 +0900</pubDate>
    </item>
    <item>
      <title>[해피CGI][cgimall] Autumn Note - 위지윅 에디터</title>
      <link>https://happycgi.tistory.com/4058</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;401&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5UMmT/dJMcad3ryd7/hEYSxQ5Y7DXeIHIFiTUQmK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5UMmT/dJMcad3ryd7/hEYSxQ5Y7DXeIHIFiTUQmK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5UMmT/dJMcad3ryd7/hEYSxQ5Y7DXeIHIFiTUQmK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5UMmT%2FdJMcad3ryd7%2FhEYSxQ5Y7DXeIHIFiTUQmK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;715&quot; height=&quot;401&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;401&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# 라이센스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MIT License&lt;/b&gt; (상업적 이용 가능, 자유로운 수정&amp;middot;배포 가능)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;# 특징 및 설명&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;텍스트 편집&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;굵게, 기울임, 밑줄, 취소선, 위첨자, 아래첨자&lt;/li&gt;
&lt;li&gt;6단계 제목, 인용구, 코드블록 단락 스타일&lt;/li&gt;
&lt;li&gt;10종 내장 글꼴(커스텀 글꼴 추가 가능), 줄간격 조절&lt;/li&gt;
&lt;li&gt;글자색&amp;middot;형광펜 컬러 픽커, 좌/중/우/양쪽 정렬&lt;/li&gt;
&lt;li&gt;순서/비순서/체크리스트 목록, 들여쓰기/내어쓰기&lt;/li&gt;
&lt;li&gt;Undo/Redo 히스토리 (단축키 지원)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;미디어 삽입&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이미지: URL/파일 업로드, base64 임베드 또는 서버 업로드 지원&lt;/li&gt;
&lt;li&gt;인라인 이미지 자르기 도구 내장&lt;/li&gt;
&lt;li&gt;동영상: YouTube, Vimeo, MP4/WebM/OGG 직접 URL을 반응형 아이프레임&amp;middot;video 태그로 렌더링&lt;/li&gt;
&lt;li&gt;표: 그리드 픽커로 직관적 삽입&lt;/li&gt;
&lt;li&gt;이모지 픽커: 7개 카테고리 380종 + 키워드 검색&lt;/li&gt;
&lt;li&gt;FontAwesome 아이콘 픽커: 스타일&amp;middot;크기&amp;middot;색상 설정 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;편의 기능&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;찾기&amp;middot;바꾸기 다이얼로그 (Ctrl+F / Ctrl+H)&lt;/li&gt;
&lt;li&gt;우클릭 컨텍스트 메뉴&lt;/li&gt;
&lt;li&gt;스크롤 시 상단 고정되는 sticky 툴바&lt;/li&gt;
&lt;li&gt;라이트/다크 테마&lt;/li&gt;
&lt;li&gt;상태바: 실시간 단어/글자 수 표시 + 드래그로 높이 조절&lt;/li&gt;
&lt;li&gt;HTML 소스 보기 모드&lt;/li&gt;
&lt;li&gt;localStorage 자동 저장 (auto-save)&lt;/li&gt;
&lt;li&gt;읽기 전용 모드&lt;/li&gt;
&lt;li&gt;8개 언어 로케일 내장 (한국어 'ko' 포함)&lt;/li&gt;
&lt;li&gt;RTL(우&amp;rarr;좌) 레이아웃 지원&lt;/li&gt;
&lt;li&gt;키보드 단축키 다이얼로그 (Shift+?)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;개발자 친화 기능&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다중 인스턴스 지원 (페이지당 여러 에디터, 각각 독립 상태)&lt;/li&gt;
&lt;li&gt;Bootstrap 4/5 클래스 자동 적용 옵션&lt;/li&gt;
&lt;li&gt;Prism.js 자동 연동 코드 하이라이트&lt;/li&gt;
&lt;li&gt;붙여넣기 살균 및 Markdown 단축 입력 변환&lt;/li&gt;
&lt;li&gt;풍부한 이벤트 시스템 (change, paste, selectionChange, charLimitReached 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;키보드 단축키&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl + Z&lt;/td&gt;
&lt;td&gt;실행 취소(Undo)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl + Shift + Z / Ctrl + Y&lt;/td&gt;
&lt;td&gt;다시 실행(Redo)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl + B&lt;/td&gt;
&lt;td&gt;굵게&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl + I&lt;/td&gt;
&lt;td&gt;기울임&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl + U&lt;/td&gt;
&lt;td&gt;밑줄&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl + F&lt;/td&gt;
&lt;td&gt;찾기 다이얼로그 열기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl + H&lt;/td&gt;
&lt;td&gt;찾기&amp;middot;바꾸기 다이얼로그 열기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shift + Enter&lt;/td&gt;
&lt;td&gt;줄바꿈 삽입&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tab&lt;/td&gt;
&lt;td&gt;공백 삽입 / 목록 들여쓰기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shift + Tab&lt;/td&gt;
&lt;td&gt;목록 내어쓰기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shift + ?&lt;/td&gt;
&lt;td&gt;단축키 도움말 다이얼로그&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;단축키 동작&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;추천 활용처&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CMS 게시판 글쓰기, 관리자 페이지 콘텐츠 입력, 매뉴얼&amp;middot;문서 작성 도구, 메일&amp;middot;뉴스레터 작성기, 댓글&amp;middot;리뷰 입력창 등.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;참고 링크&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GitHub 원본: &lt;a href=&quot;https://github.com/cmm-cmm/Autumn-Note&quot;&gt;https://github.com/cmm-cmm/Autumn-Note&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;라이브 데모: &lt;a href=&quot;https://www.cssscript.com/demo/wysiwyg-editor-autumn-note&quot;&gt;cssscript.com 데모&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;&lt;br /&gt;# 설치방법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;① 패키지 매니저 설치&lt;/h3&gt;
&lt;pre class=&quot;clean&quot; style=&quot;background-color: #f5f5f5;&quot;&gt;&lt;code&gt;npm install autumnnote # 또는 yarn add autumnnote # 또는 pnpm install autumnnote&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;clean&quot; style=&quot;background-color: #f5f5f5;&quot;&gt;&lt;code&gt;import AutumnNote from 'autumnnote'; import 'autumnnote/dist/autumnnote.css';&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;② CDN 방식&lt;/h3&gt;
&lt;pre class=&quot;&quot; style=&quot;background-color: #f5f5f5;&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;③ 기본 사용&lt;/h3&gt;
&lt;pre class=&quot;actionscript&quot; style=&quot;background-color: #f5f5f5;&quot;&gt;&lt;code&gt;const editor = AutumnNote.create('#article-editor', {   // 옵션 설정 });&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;④ 서버 업로드 처리 예시&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;background-color: #f5f5f5;&quot;&gt;&lt;code&gt;const editor = AutumnNote.create('#article-editor', {   onImageUpload(files) {     const payload = new FormData();     payload.append('image', files[0]);     fetch('/media/images/upload', { method: 'POST', body: payload })       .then(res =&amp;gt; res.json())       .then(({ url }) =&amp;gt; editor.insertImage(url, files[0].name));   }, });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ FontAwesome이 페이지에 로드되어 있으면 자동 감지되어 FA 아이콘을 사용하고, 없으면 내장 SVG 아이콘으로 대체됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;중요 옵션&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;placeholder&lt;/td&gt;
&lt;td&gt;빈 에디터에 표시할 안내 문구&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;height&lt;/td&gt;
&lt;td&gt;초기 높이(px)&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;minHeight / maxHeight&lt;/td&gt;
&lt;td&gt;최소/최대 높이(px), 0은 무제한&lt;/td&gt;
&lt;td&gt;100 / 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;toolbar&lt;/td&gt;
&lt;td&gt;툴바 버튼 그룹 배열로 커스터마이징&lt;/td&gt;
&lt;td&gt;전체 버튼&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;toolbarOverflow&lt;/td&gt;
&lt;td&gt;툴바 넘침 처리 ('wrap' 또는 'scroll')&lt;/td&gt;
&lt;td&gt;wrap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;theme&lt;/td&gt;
&lt;td&gt;테마 ('light' 또는 'dark')&lt;/td&gt;
&lt;td&gt;light&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lang&lt;/td&gt;
&lt;td&gt;UI 언어 ('ko', 'en', 'ja', 'zh', 'vi', 'fr', 'de', 'es')&lt;/td&gt;
&lt;td&gt;en&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;direction&lt;/td&gt;
&lt;td&gt;텍스트 방향 ('ltr' 또는 'rtl')&lt;/td&gt;
&lt;td&gt;ltr&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;autoSave / autoSaveKey&lt;/td&gt;
&lt;td&gt;localStorage 자동 저장 활성화 및 키 지정&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;readOnly&lt;/td&gt;
&lt;td&gt;읽기 전용 모드&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;allowImageUpload&lt;/td&gt;
&lt;td&gt;이미지 드래그/붙여넣기/업로드 허용&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;maxImageSize&lt;/td&gt;
&lt;td&gt;최대 이미지 크기(MB)&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;maxChars / maxWords&lt;/td&gt;
&lt;td&gt;최대 글자/단어 수 제한, 0은 무제한&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pasteAsPlainText&lt;/td&gt;
&lt;td&gt;붙여넣기 시 서식 제거&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pasteCleanHTML&lt;/td&gt;
&lt;td&gt;붙여넣기 시 HTML 살균&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;markdownPaste&lt;/td&gt;
&lt;td&gt;Markdown 단축 입력을 HTML로 변환&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;stickyToolbar / stickyToolbarOffset&lt;/td&gt;
&lt;td&gt;스크롤 시 툴바 상단 고정 및 오프셋(px)&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useBootstrap / bootstrapVersion&lt;/td&gt;
&lt;td&gt;Bootstrap CSS 클래스 적용 (4 또는 5)&lt;/td&gt;
&lt;td&gt;false / 5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;codeHighlight&lt;/td&gt;
&lt;td&gt;Prism.js 자동 로드로 코드 블록 하이라이트&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;colorSwatches&lt;/td&gt;
&lt;td&gt;색상 팔레트 앞에 추가할 브랜드 컬러 배열&lt;/td&gt;
&lt;td&gt;[ ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onChange / onFocus / onBlur / onInit&lt;/td&gt;
&lt;td&gt;콘텐츠 변경 / 포커스 / 블러 / 초기화 콜백&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onImageUpload / onImageError&lt;/td&gt;
&lt;td&gt;커스텀 업로드 핸들러 / 이미지 거부 콜백&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;옵션명 설명 기본값&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;주요 API 메서드&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;editor.getHTML()&lt;/td&gt;
&lt;td&gt;살균된 HTML 반환 (폼 제출용)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;editor.setHTML(html)&lt;/td&gt;
&lt;td&gt;콘텐츠 설정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;editor.getText()&lt;/td&gt;
&lt;td&gt;평문 텍스트 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;editor.clear()&lt;/td&gt;
&lt;td&gt;콘텐츠 비우기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;editor.destroy()&lt;/td&gt;
&lt;td&gt;에디터 제거 및 원래 DOM 복원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;editor.setDisabled(bool)&lt;/td&gt;
&lt;td&gt;에디터&amp;middot;툴바 활성/비활성 전환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;editor.on(event, handler) / editor.off(event, handler)&lt;/td&gt;
&lt;td&gt;이벤트 리스너 등록/해제&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;메서드 설명&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;&gt;&lt;a href=&quot;https://happycgi.com/program/detail.php?number=18163&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bguOPF/dJMcahLAZrj/KMChb3jbqLDmCJrk39ZO3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbguOPF%2FdJMcahLAZrj%2FKMChb3jbqLDmCJrk39ZO3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;140&quot; height=&quot;40&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>웹프로그램밍 자료실/JAVA 자료</category>
      <category>CGIMALL</category>
      <category>happycgi</category>
      <category>에디터</category>
      <category>위지윅</category>
      <category>해피CGI</category>
      <author>해피CGI윤실장</author>
      <guid isPermaLink="true">https://happycgi.tistory.com/4058</guid>
      <comments>https://happycgi.tistory.com/4058#entry4058comment</comments>
      <pubDate>Fri, 19 Jun 2026 09:14:14 +0900</pubDate>
    </item>
    <item>
      <title>[해피CGI][cgimall] Cred App Like Tab Bar Interaction 탭메뉴 css 상호작용</title>
      <link>https://happycgi.tistory.com/4057</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;170&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckybik/dJMcac4ywks/zkGFCvoIlMfhE7PHMKk3ZK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckybik/dJMcac4ywks/zkGFCvoIlMfhE7PHMKk3ZK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckybik/dJMcac4ywks/zkGFCvoIlMfhE7PHMKk3ZK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fckybik%2FdJMcac4ywks%2FzkGFCvoIlMfhE7PHMKk3ZK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;656&quot; height=&quot;170&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;170&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;hover된 메뉴 위치로 배경(span)이 슬라이딩 이동하면서 아이콘과 텍스트가 애니메이션으로 바뀌는 네비게이션 UI 입니다&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;html&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;351&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lmrUJ/dJMcahEL7Ey/B0mMZMdhVbUzSW6bH7VRy1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lmrUJ/dJMcahEL7Ey/B0mMZMdhVbUzSW6bH7VRy1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lmrUJ/dJMcahEL7Ey/B0mMZMdhVbUzSW6bH7VRy1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlmrUJ%2FdJMcahEL7Ey%2FB0mMZMdhVbUzSW6bH7VRy1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;580&quot; height=&quot;351&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;351&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;css&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;655&quot; data-origin-height=&quot;2108&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5GUPX/dJMcac4ywkt/MfFczGk2diQoAqsQy35LLK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5GUPX/dJMcac4ywkt/MfFczGk2diQoAqsQy35LLK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5GUPX/dJMcac4ywkt/MfFczGk2diQoAqsQy35LLK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5GUPX%2FdJMcac4ywkt%2FMfFczGk2diQoAqsQy35LLK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;655&quot; height=&quot;2108&quot; data-origin-width=&quot;655&quot; data-origin-height=&quot;2108&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;해당 사이트 또는 첨부파일에서 원본 소스를 확인할 수 있습니다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;&gt;&lt;a href=&quot;https://happycgi.com/program/detail.php?number=18162&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8jicc/dJMcaf1grqp/woRFGlkLb8ksaV2ATIpnwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8jicc%2FdJMcaf1grqp%2FwoRFGlkLb8ksaV2ATIpnwK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;140&quot; height=&quot;40&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>웹프로그램밍 자료실/기타 자료</category>
      <category>CGIMALL</category>
      <category>happycgi</category>
      <category>탭메뉴</category>
      <category>해피CGI</category>
      <author>해피CGI윤실장</author>
      <guid isPermaLink="true">https://happycgi.tistory.com/4057</guid>
      <comments>https://happycgi.tistory.com/4057#entry4057comment</comments>
      <pubDate>Thu, 18 Jun 2026 09:06:29 +0900</pubDate>
    </item>
    <item>
      <title>[해피CGI][cgimall] Textarea auto-expand 입력되는 내용에 따라 높이가 조절되는 textarea</title>
      <link>https://happycgi.tistory.com/4056</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;561&quot; data-origin-height=&quot;250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dNV5Te/dJMcacKjugE/Dd9kObbOG4M7KVnj1ChDg1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dNV5Te/dJMcacKjugE/Dd9kObbOG4M7KVnj1ChDg1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dNV5Te/dJMcacKjugE/Dd9kObbOG4M7KVnj1ChDg1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdNV5Te%2FdJMcacKjugE%2FDd9kObbOG4M7KVnj1ChDg1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;561&quot; height=&quot;250&quot; data-origin-width=&quot;561&quot; data-origin-height=&quot;250&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;html&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;611&quot; data-origin-height=&quot;54&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpSTGZ/dJMcaaFJx7P/ZdwuFTo2pPo4Uk80NxvLek/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpSTGZ/dJMcaaFJx7P/ZdwuFTo2pPo4Uk80NxvLek/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpSTGZ/dJMcaaFJx7P/ZdwuFTo2pPo4Uk80NxvLek/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpSTGZ%2FdJMcaaFJx7P%2FZdwuFTo2pPo4Uk80NxvLek%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;611&quot; height=&quot;54&quot; data-origin-width=&quot;611&quot; data-origin-height=&quot;54&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;css&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;282&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wZe3F/dJMcabdsjH3/AKyfnsFBAD2TaVoTJoQJVK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wZe3F/dJMcabdsjH3/AKyfnsFBAD2TaVoTJoQJVK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wZe3F/dJMcabdsjH3/AKyfnsFBAD2TaVoTJoQJVK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwZe3F%2FdJMcabdsjH3%2FAKyfnsFBAD2TaVoTJoQJVK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;440&quot; height=&quot;282&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;282&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;js&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;319&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tNnWu/dJMcaaFJx7Q/jx5zmcFZZTkYumYC28icKk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tNnWu/dJMcaaFJx7Q/jx5zmcFZZTkYumYC28icKk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tNnWu/dJMcaaFJx7Q/jx5zmcFZZTkYumYC28icKk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtNnWu%2FdJMcaaFJx7Q%2Fjx5zmcFZZTkYumYC28icKk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;540&quot; height=&quot;319&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;319&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;사용자의 입력에 따라 높이가 자동으로 조절되는 textarea를 만들 수 있습니다.&lt;br /&gt;입력하는 내용에 맞춰 줄바꿈이 일어날 때마다 textarea의 높이가 자연스럽게 늘어납니다.&lt;br /&gt;&lt;br /&gt;해당사이트 또는 첨부파일을 다운로드 받아 소스를 확인할 수 있습니다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;&gt;&lt;a href=&quot;https://happycgi.com/program/detail.php?number=18161&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7UpFa/dJMcac4xCZt/LsfrzOAY76Nye8xTiK2f51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7UpFa%2FdJMcac4xCZt%2FLsfrzOAY76Nye8xTiK2f51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;140&quot; height=&quot;40&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>웹프로그램밍 자료실/JAVA 자료</category>
      <category>CGIMALL</category>
      <category>happycgi</category>
      <category>textarea</category>
      <category>해피CGI</category>
      <author>해피CGI윤실장</author>
      <guid isPermaLink="true">https://happycgi.tistory.com/4056</guid>
      <comments>https://happycgi.tistory.com/4056#entry4056comment</comments>
      <pubDate>Wed, 17 Jun 2026 09:06:40 +0900</pubDate>
    </item>
    <item>
      <title>[해피CGI][cgimall] 스크롤 상태 기반 Sticky 네비게이션 UI</title>
      <link>https://happycgi.tistory.com/4055</link>
      <description>&lt;div&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;애니메이션 탭 표시줄은 애니메이션과 전환을 사용하여 사용자에게 더욱 직관적인 인터페이스를 제공해 줄 수 있습니다.&lt;br /&gt;사람이 탭을 클릭하면 해당 탭과 관련된 콘텐츠가 쉬운 애니메이션으로 표시하게 됩니다.&lt;br /&gt;애니메이션 탭 표시줄은 웹페이지 좀더 역동적이고 매력적으로 만들 수 있습니다.&lt;br /&gt;&lt;br /&gt;모든 탭과 관련된 콘텐츠를 쉬운 애니메이션으로 보여줌으로써 현재 웹 사이트 또는 앱의 어느 부분에 있는지, &lt;br /&gt;다른 섹션으로 이동하는 방법을 쉽게 이해할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;208&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LGJYG/dJMcahLyqzD/O1BwubWxLFZMES67IrxLJk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LGJYG/dJMcahLyqzD/O1BwubWxLFZMES67IrxLJk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LGJYG/dJMcahLyqzD/O1BwubWxLFZMES67IrxLJk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/LGJYG/dJMcahLyqzD/O1BwubWxLFZMES67IrxLJk/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;208&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;208&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;h2 style=&quot;color: #0032b2;&quot; data-ke-size=&quot;size26&quot;&gt;HTML 구조&lt;/h2&gt;
&lt;div style=&quot;background-color: #f5f2f0;&quot;&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;lt;header&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;lt;h1&amp;gt;Scroll down&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;lt;p&amp;gt;This is just filler for this section, &amp;lt;a href=&quot;#services&quot;&amp;gt;scroll on&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;lt;div class=&quot;stuck-top&quot;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;lt;nav&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;lt;a href=&quot;#services&quot;&amp;gt;Services&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;lt;a href=&quot;#journal&quot;&amp;gt;Journal&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;lt;a href=&quot;#about&quot;&amp;gt;About&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;lt;a href=&quot;#contact&quot;&amp;gt;Contact&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;lt;/nav&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;lt;section id=&quot;services&quot; style=&quot;view-timeline-name: --section-services&quot;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;lt;header&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;lt;h1&amp;gt;Services&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;lt;p&amp;gt;Filler for this section, &amp;lt;a href=&quot;#journal&quot;&amp;gt;scroll on&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;lt;/header&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;lt;section id=&quot;journal&quot; style=&quot;view-timeline-name: --section-journal&quot;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;lt;header&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;lt;h1&amp;gt;Journal&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;lt;p&amp;gt;Filler for this section, &amp;lt;a href=&quot;#about&quot;&amp;gt;scroll on&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;lt;/header&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;lt;section id=&quot;about&quot; style=&quot;view-timeline-name: --section-about&quot;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;lt;header&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;lt;h1&amp;gt;About&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;lt;p&amp;gt;Filler for this section, &amp;lt;a href=&quot;#contact&quot;&amp;gt;scroll on&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;lt;/header&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;lt;section id=&quot;contact&quot; style=&quot;view-timeline-name: --section-contact&quot;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;lt;header&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;lt;h1&amp;gt;Contact&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;lt;p&amp;gt;Done, no more sections. &amp;lt;a href=&quot;#&quot;&amp;gt;Scroll to top&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;lt;/header&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;h2 style=&quot;color: #d22800;&quot; data-ke-size=&quot;size26&quot;&gt;CSS 소스&lt;/h2&gt;
&lt;div style=&quot;background-color: #f5f2f0;&quot;&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;@import url(&quot;&lt;a href=&quot;https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&amp;amp;display=swap&quot;&gt;https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&amp;amp;display=swap&lt;/a&gt;&quot;);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;@import &quot;&lt;a href=&quot;https://unpkg.com/open-props&quot;&gt;https://unpkg.com/open-props&lt;/a&gt;&quot; layer(design.system);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;@layer demo {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; .stuck-top {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; position: sticky;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; container-type: scroll-state;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; top: var(--space-s);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; z-index: 1;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;gt; nav {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; transition:&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; background-color 0.3s var(--ease-3),&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; box-shadow 0.3s var(--ease-3), margin 0.3s var(--ease-spring-3),&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; border-radius 0.3s var(--ease-3);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; @container scroll-state(stuck: top) {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; background-color: oklch(from var(--color-onPrimary) l c h / 0.4);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; backdrop-filter: blur(10px);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; box-shadow: var(--shadow-6);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; border-radius: 10px;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; margin-inline: 20px;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;@layer demo.scrollspy {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; body {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; timeline-scope: --section-services, --section-journal, --section-about, --section-contact;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; @keyframes highlight {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 25%, 50% {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; border-block-end-color: oklch(from var(--color-primary) l c h / 0.4);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; color: oklch(from var(--color-primary) calc(l * 1.2) c h );&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; nav {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;gt; a {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; animation: highlight linear both;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; animation-range: cover 20% exit-crossing 50%;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; border-block-end: 3px solid transparent;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;gt; a:nth-child(1) { animation-timeline: --section-services }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;gt; a:nth-child(2) { animation-timeline: --section-journal }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;gt; a:nth-child(3) { animation-timeline: --section-about }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;gt; a:nth-child(4) { animation-timeline: --section-contact }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;@layer demo.support {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; :root {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; /* Override open props shadow strength */&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --shadow-strength: 0.5%;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --color-primary: #ddd5c3;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --color-onPrimary: #6f8d6a;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --color-emphasis: #496c45;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; /* @link &lt;a href=&quot;https://utopia.fyi/type/calculator?c=320,18,1.25,1440,28,1.333,5,2,&amp;amp;s=0.75&quot;&gt;https://utopia.fyi/type/calculator?c=320,18,1.25,1440,28,1.333,5,2,&amp;amp;s=0.75&lt;/a&gt;|0.5|0.25,1.5|2|3|4|6,s-l&amp;amp;g=s,l,xl,12 */&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --step--2: clamp(0.72rem, 0.7046rem + 0.0769vw, 0.7738rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --step--1: clamp(0.9rem, 0.8624rem + 0.1879vw, 1.0315rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --step-0: clamp(1.125rem, 1.0536rem + 0.3571vw, 1.375rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --step-1: clamp(1.4063rem, 1.2844rem + 0.6095vw, 1.8329rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --step-2: clamp(1.7578rem, 1.562rem + 0.9792vw, 2.4432rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --step-3: clamp(2.1973rem, 1.8945rem + 1.5136vw, 3.2568rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --step-4: clamp(2.7466rem, 2.2909rem + 2.2782vw, 4.3413rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --step-5: clamp(3.4332rem, 2.7607rem + 3.3625vw, 5.787rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; /* @link &lt;a href=&quot;https://utopia.fyi/space/calculator?c=320,18,1.25,1440,22,1.333,5,2,&amp;amp;s=0.75&quot;&gt;https://utopia.fyi/space/calculator?c=320,18,1.25,1440,22,1.333,5,2,&amp;amp;s=0.75&lt;/a&gt;|0.5|0.25,1.5|2|3|4|6,s-l&amp;amp;g=s,l,xl,12 */&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --space-3xs: clamp(0.3125rem, 0.2946rem + 0.0893vw, 0.375rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --space-2xs: clamp(0.5625rem, 0.5268rem + 0.1786vw, 0.6875rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --space-xs: clamp(0.875rem, 0.8214rem + 0.2679vw, 1.0625rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --space-s: clamp(1.125rem, 1.0536rem + 0.3571vw, 1.375rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --space-m: clamp(1.6875rem, 1.5804rem + 0.5357vw, 2.0625rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --space-l: clamp(2.25rem, 2.1071rem + 0.7143vw, 2.75rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --space-xl: clamp(3.375rem, 3.1607rem + 1.0714vw, 4.125rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --space-2xl: clamp(4.5rem, 4.2143rem + 1.4286vw, 5.5rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --space-3xl: clamp(6.75rem, 6.3214rem + 2.1429vw, 8.25rem);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; * {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; box-sizing: border-box;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; margin: 0;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; html {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; block-size: 100%;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; color: var(--color-primary);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; background: var(--color-emphasis);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; scroll-behavior: smooth;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; body {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; min-block-size: 100%;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; font-family: &quot;Inter&quot;, sans-serif;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; section {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; border-block-end: 2px solid var(--color-onPrimary);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; a {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; color: inherit;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; text-decoration: none;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; transition: all 200ms ease-in-out;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;amp;:hover {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; opacity: 0.8;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; header {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; display: grid;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; place-content: center;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; text-align: center;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; display: grid;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; gap: var(--space-3xs);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; block-size: 95svh;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;gt; h1 {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; font-size: var(--step-4);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; text-transform: uppercase;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; letter-spacing: var(--font-letterspacing-5);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;gt; p {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; font-size: var(--step-2);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;gt; a {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; color: oklch(from var(--color-primary) calc(l * 1.2) c h );&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; border-block-end: 3px solid oklch(from var(--color-primary) l c h / 0.4);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; .stuck-top {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; z-index: 1;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; nav {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; display: grid;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; grid-auto-flow: column;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; grid-auto-columns: 1fr;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; place-items: center;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; justify-content: space-between;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; gap: var(--space-l);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; padding: var(--space-l) var(--space-2xl);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;gt; a {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; font-size: var(--step-2);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; display: block;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; transition: all 0.2s ease-in-out;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;amp;:hover {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; opacity: 0.6;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;color: #574136;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;&gt;&lt;a href=&quot;https://happycgi.com/program/detail.php?number=18159&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwCLoI/dJMcabkjQ12/njKObkVfBvRaxAQVwCEkK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwCLoI%2FdJMcabkjQ12%2FnjKObkVfBvRaxAQVwCEkK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;140&quot; height=&quot;40&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>웹프로그램밍 자료실/기타 자료</category>
      <category>CGIMALL</category>
      <category>happycgi</category>
      <category>UI</category>
      <category>해피CGI</category>
      <author>해피CGI윤실장</author>
      <guid isPermaLink="true">https://happycgi.tistory.com/4055</guid>
      <comments>https://happycgi.tistory.com/4055#entry4055comment</comments>
      <pubDate>Tue, 16 Jun 2026 09:13:03 +0900</pubDate>
    </item>
    <item>
      <title>[해피CGI][cgimall] 스크롤 인터랙션 확장형 이미지 갤러리 UI</title>
      <link>https://happycgi.tistory.com/4054</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;CSS Grid 기반으로 구성된 이미지 갤러리에서 특정 요소 hover 시 해당 영역이 확장되도록 구현된 인터랙션이다.&lt;br /&gt;:has() 선택자를 활용하여 부모 요소에서 자식 hover 상태를 감지하고 레이아웃을 동적으로 변경한다.&lt;br /&gt;이미지는 겹치는 grid 구조와 비율 변화를 통해 자연스럽게 확장되며 시각적인 몰입감을 제공한다.&lt;br /&gt;별도의 JavaScript 없이 순수 CSS만으로 구현된 구조로, 최신 브라우저 환경에서 활용 가능한 UI 패턴이다.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HIW5C/dJMcahEJBYb/E5kZxIbL3JN2VsBbihYAn0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HIW5C/dJMcahEJBYb/E5kZxIbL3JN2VsBbihYAn0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HIW5C/dJMcahEJBYb/E5kZxIbL3JN2VsBbihYAn0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/HIW5C/dJMcahEJBYb/E5kZxIbL3JN2VsBbihYAn0/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;350&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;h2 style=&quot;color: #0032b2;&quot; data-ke-size=&quot;size26&quot;&gt;HTML 구조&lt;/h2&gt;
&lt;div style=&quot;background-color: #f5f2f0;&quot;&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;lt;div class=&quot;wrapper&quot;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;lt;&lt;span&gt;div style=&quot;--bg-img:url(&lt;a href=&quot;https://images.unsplash.com/photo-1518005020951-eccb494ad742?crop=entropy&amp;amp;cs=tinysrgb&amp;amp;fit=max&amp;amp;fm=jpg&amp;amp;ixid=M3wzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3Njg0MjEyODh8&amp;amp;ixlib=rb-4.1.0&amp;amp;q=80&amp;amp;w=400)&quot;&gt;https://images.unsplash.com/photo-1518005020951-eccb494ad742?crop=entropy&amp;amp;cs=tinysrgb&amp;amp;fit=max&amp;amp;fm=jpg&amp;amp;ixid=M3wzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3Njg0MjEyODh8&amp;amp;ixlib=rb-4.1.0&amp;amp;q=80&amp;amp;w=400)&lt;/a&gt;&quot;&amp;gt;&lt;/span&gt;&amp;lt;/div&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;lt;&lt;span&gt;div style=&quot;--bg-img:url(&lt;a href=&quot;https://images.unsplash.com/photo-1479839672679-a46483c0e7c8?crop=entropy&amp;amp;cs=tinysrgb&amp;amp;fit=max&amp;amp;fm=jpg&amp;amp;ixid=M3wzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3Njg0MjA1MDB8&amp;amp;ixlib=rb-4.1.0&amp;amp;q=80&amp;amp;w=400)&quot;&gt;https://images.unsplash.com/photo-1479839672679-a46483c0e7c8?crop=entropy&amp;amp;cs=tinysrgb&amp;amp;fit=max&amp;amp;fm=jpg&amp;amp;ixid=M3wzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3Njg0MjA1MDB8&amp;amp;ixlib=rb-4.1.0&amp;amp;q=80&amp;amp;w=400)&lt;/a&gt;&quot;&amp;gt;&lt;/span&gt; &amp;lt;/div&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;lt;&lt;span&gt;div style=&quot;--bg-img:url(&lt;a href=&quot;https://images.unsplash.com/photo-1493397212122-2b85dda8106b?crop=entropy&amp;amp;cs=tinysrgb&amp;amp;fit=max&amp;amp;fm=jpg&amp;amp;ixid=M3wzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3Njg0MjA4MTB8&amp;amp;ixlib=rb-4.1.0&amp;amp;q=80&amp;amp;w=400)&quot;&gt;https://images.unsplash.com/photo-1493397212122-2b85dda8106b?crop=entropy&amp;amp;cs=tinysrgb&amp;amp;fit=max&amp;amp;fm=jpg&amp;amp;ixid=M3wzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3Njg0MjA4MTB8&amp;amp;ixlib=rb-4.1.0&amp;amp;q=80&amp;amp;w=400)&lt;/a&gt;&quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;lt;&lt;span&gt;div style=&quot;--bg-img:url(&lt;a href=&quot;https://images.unsplash.com/photo-1524126675694-1efa3488b7c0?crop=entropy&amp;amp;cs=tinysrgb&amp;amp;fit=max&amp;amp;fm=jpg&amp;amp;ixid=M3wzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3Njg0MjA1MjR8&amp;amp;ixlib=rb-4.1.0&amp;amp;q=80&amp;amp;w=400)&quot;&gt;https://images.unsplash.com/photo-1524126675694-1efa3488b7c0?crop=entropy&amp;amp;cs=tinysrgb&amp;amp;fit=max&amp;amp;fm=jpg&amp;amp;ixid=M3wzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3Njg0MjA1MjR8&amp;amp;ixlib=rb-4.1.0&amp;amp;q=80&amp;amp;w=400)&lt;/a&gt;&lt;/span&gt;&quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #d22800;&quot; data-ke-size=&quot;size26&quot;&gt;CSS 소스&lt;/h2&gt;
&lt;div style=&quot;background-color: #f5f2f0;&quot;&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;@import url(&lt;a href=&quot;https://fonts.bunny.net/css?family=jura:300,500);&quot;&gt;https://fonts.bunny.net/css?family=jura:300,500);&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;@layer base, demo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;@layer demo {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; /* demo code goes here */&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; .wrapper{&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;--border-size: 5px;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;--border-color: var(--bg-light);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;/* default gid columns - note, to animatbale we need to defined them individually */&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --grid-cols: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr ;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; display: grid;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; grid-template-columns: var(--grid-cols);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; width:min(100%,800px);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; margin-inline: auto;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; aspect-ratio: 2/1;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; transition: grid 300ms ease-in-out;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; counter-reset: --card-counter;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; /* define grid columns according to which one has hover */&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;amp;:has(:nth-child(1):hover){ --grid-cols: 6fr 1fr 1fr&amp;nbsp; 1fr 1fr 1fr&amp;nbsp; 1fr 1fr 1fr; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;amp;:has(:nth-child(2):hover){ --grid-cols: 1fr 1fr 1fr&amp;nbsp; 6fr 1fr 1fr&amp;nbsp; 1fr 1fr 1fr; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;amp;:has(:nth-child(3):hover){ --grid-cols: 1fr 1fr 1fr&amp;nbsp; 1fr 1fr 6fr&amp;nbsp; 1fr 1fr 1fr; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;amp;:has(:nth-child(4):hover){ --grid-cols: 1fr 1fr 1fr&amp;nbsp; 1fr 1fr 1fr&amp;nbsp; 1fr 6fr 1fr; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;amp; &amp;gt; *{&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; position: relative;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; overflow: hidden;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; border-radius: 0 0 0 30%/ 0 0 0 50% ;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;amp;:first-child{&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; border-radius: 0 0 0 0/ 0 0 0 200px ;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; corner-shape:notch;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; transition: all 300ms ease-in-out;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; border: var(--border-size) solid var(--border-color);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; background-image: var(--bg-img);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; background-size: 450px 100%; /* requires fixed width to maintain size and aspect */&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;/* remove notch from current and next sibling on hover*/&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;amp;:hover,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;amp;:hover + div{&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; border-radius: 0 0 0 0;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;span&gt; &lt;/span&gt;/* define grid position - each element overlaps by 1 column */&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; grid-row: 1;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;amp;:nth-child(1){ grid-column: 1&amp;nbsp; / span 3; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;amp;:nth-child(2){ grid-column: 3&amp;nbsp; / span 3; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;amp;:nth-child(3){ grid-column: 5&amp;nbsp; / span 3; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;amp;:nth-child(4){ grid-column: 7&amp;nbsp; / span 3; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; /* image counter - could easily be a title */&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;amp;::after{&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;content: counter(--card-counter) &quot;.&quot;;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;counter-increment: --card-counter;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;position: absolute;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;top: .5rem;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;left: 1rem;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;font-size: 2rem;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;transition: scale 150ms ease-in-out;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; scale: 0;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;amp;:hover::after{&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; scale: 1;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;/* general styling not relevant for this demo */&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;@layer base {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;* {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;box-sizing: border-box;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;:root {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;color-scheme: light dark;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;--bg-dark: rgb(16, 24, 40);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;--bg-light: rgb(248, 244, 238);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;--txt-light: rgb(10, 10, 10);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;--txt-dark: rgb(245, 245, 245););&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;--line-light: rgba(0 0 0 / .25);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;--line-dark: rgba(255 255 255 / .25);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --clr-bg: light-dark(var(--bg-light), var(--bg-dark));&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --clr-txt: light-dark(var(--txt-light), var(--txt-dark));&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; --clr-lines: light-dark(var(--line-light), var(--line-dark));&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;body {&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;background-color: var(--clr-bg);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;color: var(--clr-txt);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;min-height: 100svh;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;margin: 0;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;padding: 2rem;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;font-family: &quot;Jura&quot;, sans-serif;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;font-size: 1rem;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;line-height: 1.5;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; display: grid;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; place-items: center;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; gap: 2rem;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;&gt;&lt;a href=&quot;https://happycgi.com/program/detail.php?number=18158&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m0Bfu/dJMcagZ7AXq/b0fedkQjc9KZJIcoBOGtGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm0Bfu%2FdJMcagZ7AXq%2Fb0fedkQjc9KZJIcoBOGtGK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;140&quot; height=&quot;40&quot; data-filename=&quot;0000.png&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>웹프로그램밍 자료실/기타 자료</category>
      <category>CGIMALL</category>
      <category>happycgi</category>
      <category>갤러리</category>
      <category>해피CGI</category>
      <author>해피CGI윤실장</author>
      <guid isPermaLink="true">https://happycgi.tistory.com/4054</guid>
      <comments>https://happycgi.tistory.com/4054#entry4054comment</comments>
      <pubDate>Mon, 15 Jun 2026 09:26:36 +0900</pubDate>
    </item>
  </channel>
</rss>