Crear skins y layouts
El skin es la apariencia de un módulo y el layout es el marco de todo el sitio. Se crean casi de la misma forma; lo que cambia es dónde se ubican y el archivo de declaración.
| Ubicación | Archivo de declaración | Se aplica a | |
|---|---|---|---|
| Skin de módulo | modules/{module}/skins/{skin}/ | skin.xml | Las instancias (mid) de ese módulo |
| Layout | layouts/{layout}/ | conf/info.xml | El sitio (o por mid) |
Crear un skin de módulo
Para darle una apariencia nueva a un módulo existente, empieza copiando completa la carpeta skins/default/ de ese módulo y cambiándole el nombre. El skin predeterminado es la referencia de qué archivos de plantilla se necesitan y qué variables se reciben.
modules/board/skins/myskin/
├── skin.xml
├── list.html ← 목록 (+ 상세는 _read.html 포함 방식)
├── _read.html
├── _comment.html
├── write_form.html
├── css/skin.css
└── ...skin.xml
<?xml version="1.0" encoding="UTF-8"?>
<skin version="0.2">
<responsive>true</responsive>
<title xml:lang="ko">내 스킨</title>
<description xml:lang="ko">설명</description>
<version>1.0.0</version>
<date>2026-08-05</date>
<author email_address="you@example.com" link="https://example.com">
<name xml:lang="ko">제작자</name>
</author>
<extra_vars>
<var name="list_style" type="select" default="list">
<title xml:lang="ko">목록 형태</title>
<options value="list"><title xml:lang="ko">목록형</title></options>
<options value="card"><title xml:lang="ko">카드형</title></options>
</var>
</extra_vars>
</skin><responsive>true</responsive>indica que el skin funciona también en pantallas angostas. Consulta Vistas responsivas y visualización responsiva.- Los ajustes de skin declarados con
<extra_vars>se leen en la plantilla con$module_info->{variable}.
Lo que debes respetar
- El skin solo cambia la pantalla. Las variables que envía el servidor y las convenciones de los formularios deben mantenerse iguales a las del skin predeterminado. Si omites los campos hidden del formulario (module, act, mid, etc.), no se guardará.
- Las partes vinculadas a la configuración de administración, como las columnas de la lista del tablero (
$list_config, etc.), no las escribas fijas en el código: sigue los valores de configuración. - Para los íconos se recomienda SVG en línea en lugar de archivos de imagen.
Crear un layout
layouts/mylayout/
├── layout.html ← 뼈대. {!! $content !!} 자리에 본문이 들어감
├── conf/info.xml
├── css/layout.css
└── js/layout.jsEstructura mínima de layout.html
@version(2)
@load('css/layout.css')
@load('js/layout.js')
<div class="my-layout">
<header>
<a href="{{ getUrl('') }}">{{ $layout_info->logo_text ?: '사이트' }}</a>
<nav>
@foreach ($gnb->list ?? [] as $item)
<a href="{{ $item['href'] }}" @if (!empty($item['selected'])) class="on" @endif>{{ $item['text'] }}</a>
@endforeach
</nav>
</header>
<main>{!! $content !!}</main>
<footer>{{ $layout_info->copyright }}</footer>
</div>- El contenido se imprime con
{!! $content !!}. No debe escaparse. - Los menús llegan como
$gnb->list, etc., según la declaración<menus>de info.xml. Cada elemento tienetext(nombre),href(dirección),selected/open(ubicación actual) ylist(submenú).
conf/info.xml
<?xml version="1.0" encoding="UTF-8"?>
<layout version="0.2">
<responsive>true</responsive>
<title xml:lang="ko">내 레이아웃</title>
<version>1.0.0</version>
<author email_address="you@example.com" link="https://example.com">
<name xml:lang="ko">제작자</name>
</author>
<menus>
<menu name="gnb" maxdepth="3" default="true">
<title xml:lang="ko">상단 메뉴</title>
</menu>
</menus>
<extra_vars>
<group>
<title xml:lang="ko">기본</title>
<var name="logo_text" type="text">
<title xml:lang="ko">로고 텍스트</title>
</var>
<var name="point_color" type="color" default="#2677e3">
<title xml:lang="ko">포인트 색상</title>
</var>
</group>
</extra_vars>
</layout>- Pon siempre los
<var>de extra_vars dentro de un<group>. La configuración detallada del layout dibuja cada grupo como una pestaña, así que las variables fuera de un grupo no aparecen en pantalla. - Los valores de configuración se leen en la plantilla con
$layout_info->{variable}. - Los elementos que se repiten, como sliders o banners, decláralos como campos repetibles.
Lo que debes respetar en el CSS del layout
- Declara siempre también
html, body { margin: 0; background: ... }. Si solo pintas el fondo del div superior, el margen predeterminado del body y el espacio de la barra de desplazamiento quedan en blanco y, en modo oscuro, se ven como un borde blanco alrededor de la pantalla. - Si soportas modo oscuro, reúne los colores en variables CSS y cámbialos con el atributo
data-themeo conprefers-color-scheme. - Si recibes un ajuste de color de acento, es más fácil de mantener pasarlo como variable, por ejemplo
style="--brand: {{ $layout_info->point_color }}", para que todo el CSS lo siga.
Distribución
Los skins y los layouts se comprimen con su carpeta y se registran en la tienda, o se instalan directamente (subiéndolos a la ruta correspondiente). Para distribuir un layout y skins de módulos como conjunto, agrúpalos en un paquete de tema.