2.1 Sciter HTML扩展

标准HTML支持

Sciter支持大部分HTML5标准,但也有一些独特的扩展和限制。

支持的HTML元素

<!-- 基本结构元素 -->
<html>, <head>, <body>, <title>
<div>, <span>, <section>, <article>, <header>, <footer>
<nav>, <aside>, <main>

<!-- 文本元素 -->
<h1>-<h6>, <p>, <br>, <hr>
<strong>, <em>, <b>, <i>, <u>, <s>
<code>, <pre>, <blockquote>

<!-- 列表元素 -->
<ul>, <ol>, <li>
<dl>, <dt>, <dd>

<!-- 表格元素 -->
<table>, <thead>, <tbody>, <tfoot>
<tr>, <th>, <td>
<caption>, <colgroup>, <col>

<!-- 表单元素 -->
<form>, <input>, <textarea>, <select>, <option>
<button>, <label>, <fieldset>, <legend>

<!-- 媒体元素 -->
<img>, <video>, <audio>
<canvas>, <svg>

<!-- 链接和脚本 -->
<a>, <link>, <script>, <style>

Sciter特有元素

1. <popup> 元素

<!-- 弹出窗口容器 -->
<popup class="context-menu">
    <menu>
        <li>复制</li>
        <li>粘贴</li>
        <li>删除</li>
    </menu>
</popup>

2. <frame> 元素

<!-- 内嵌框架,类似iframe但更轻量 -->
<frame src="child-window.htm" />

3. <widget> 元素

<!-- 自定义控件容器 -->
<widget type="calendar" value="2024-01-15" />
<widget type="slider" min="0" max="100" value="50" />

4. <htmlarea> 元素

<!-- 富文本编辑器 -->
<htmlarea spellcheck="true">
    <p>可编辑的富文本内容</p>
</htmlarea>

HTML属性扩展

1. 行为属性 (behavior)

<!-- 为元素添加特殊行为 -->
<div behavior="button">自定义按钮</div>
<div behavior="hyperlink" href="#section1">内部链接</div>
<input behavior="masked-edit" mask="(###) ###-####" />
<div behavior="collapsible">可折叠内容</div>

2. 状态属性

<!-- 元素状态控制 -->
<button state-disabled="true">禁用按钮</button>
<div state-expanded="false">折叠状态</div>
<input state-readonly="true" value="只读文本" />

3. 数据绑定属性

<!-- 数据绑定 -->
<div data-bind="text: userName">用户名</div>
<input data-bind="value: email" />
<img data-bind="src: avatarUrl" />

2.2 Sciter CSS增强

CSS选择器扩展

1. 状态选择器

/* 元素状态选择器 */
button:disabled { opacity: 0.5; }
button:pressed { transform: scale(0.95); }
input:focus { border-color: #007acc; }
div:expanded { height: auto; }
div:collapsed { height: 0; }

/* 自定义状态 */
.item:current { background: #e3f2fd; }
.item:selected { background: #1976d2; color: white; }

2. 结构选择器增强

/* 扩展的结构选择器 */
li:nth-child(odd) { background: #f5f5f5; }
li:nth-child(even) { background: white; }

/* 范围选择器 */
li:nth-child(2n+1):nth-child(-n+10) {
    /* 选择前10个奇数项 */
    color: red;
}

CSS属性扩展

1. 流式布局 (flow)

/* Sciter独有的流式布局 */
.container {
    flow: horizontal; /* 水平流式布局 */
}

.vertical-container {
    flow: vertical; /* 垂直流式布局 */
}

.stack-container {
    flow: stack; /* 堆叠布局 */
}

.grid-container {
    flow: grid(3, 1fr); /* 网格布局 */
}

/* 流式布局示例 */
.toolbar {
    flow: horizontal;
    padding: 8px;
    gap: 4px;
}

.toolbar > button {
    padding: 6px 12px;
    border: 1px solid #ccc;
    background: #f8f9fa;
}

.sidebar {
    flow: vertical;
    width: 200px;
    height: *; /* 自适应高度 */
}

.content-area {
    flow: vertical;
    width: *; /* 自适应宽度 */
    height: *;
}

2. 尺寸单位扩展

/* Sciter特有的尺寸单位 */
.element {
    width: *; /* 自适应宽度 */
    height: *; /* 自适应高度 */
    
    width: 1*; /* 权重为1的自适应 */
    height: 2*; /* 权重为2的自适应 */
    
    min-width: min-content; /* 最小内容宽度 */
    max-width: max-content; /* 最大内容宽度 */
}

/* 百分比和固定尺寸混合 */
.layout {
    width: 300px + 50%; /* 固定宽度 + 百分比 */
    height: 100px + 1*; /* 固定高度 + 自适应 */
}

3. 背景和边框增强

/* 渐变背景 */
.gradient-bg {
    background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
    background: radial-gradient(circle, #667eea, #764ba2);
}

/* 多重背景 */
.multi-bg {
    background: 
        url(pattern.png) repeat,
        linear-gradient(to bottom, #fff, #f0f0f0);
}

/* 边框图像 */
.border-image {
    border: 10px solid transparent;
    border-image: url(border.png) 10 repeat;
}

/* 圆角和阴影 */
.card {
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    background: white;
}

4. 变换和动画

/* 2D变换 */
.transform-element {
    transform: rotate(45deg) scale(1.2) translate(10px, 20px);
    transform-origin: center center;
}

/* 过渡动画 */
.animated-button {
    transition: all 0.3s ease;
    background: #007acc;
    color: white;
}

.animated-button:hover {
    background: #005a9e;
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0, 122, 204, 0.3);
}

/* 关键帧动画 */
@keyframes pulse {
    0% { transform: scale(1); }
    50% { transform: scale(1.05); }
    100% { transform: scale(1); }
}

.pulse-animation {
    animation: pulse 2s infinite;
}

@keyframes slideIn {
    from {
        opacity: 0;
        transform: translateX(-100%);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

.slide-in {
    animation: slideIn 0.5s ease-out;
}

响应式设计

1. 媒体查询

/* 基于窗口大小的媒体查询 */
@media (max-width: 768px) {
    .container {
        flow: vertical;
        padding: 10px;
    }
    
    .sidebar {
        width: 100%;
        height: auto;
    }
}

@media (min-width: 1200px) {
    .container {
        max-width: 1140px;
        margin: 0 auto;
    }
}

/* 基于设备特性的查询 */
@media (pointer: coarse) {
    /* 触摸设备样式 */
    button {
        min-height: 44px;
        min-width: 44px;
    }
}

@media (hover: hover) {
    /* 支持悬停的设备 */
    .hover-effect:hover {
        background: #f0f0f0;
    }
}

2. 弹性布局

/* Flexbox布局 */
.flex-container {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
}

.flex-item {
    flex: 1; /* 等分剩余空间 */
}

.flex-item.grow {
    flex-grow: 2; /* 增长因子 */
}

.flex-item.shrink {
    flex-shrink: 0; /* 不收缩 */
}

/* 网格布局 */
.grid-container {
    display: grid;
    grid-template-columns: 200px 1fr 200px;
    grid-template-rows: auto 1fr auto;
    grid-gap: 16px;
    height: 100vh;
}

.header {
    grid-column: 1 / -1;
    grid-row: 1;
}

.sidebar {
    grid-column: 1;
    grid-row: 2;
}

.main {
    grid-column: 2;
    grid-row: 2;
}

.aside {
    grid-column: 3;
    grid-row: 2;
}

.footer {
    grid-column: 1 / -1;
    grid-row: 3;
}

2.3 实用CSS组件

按钮组件

/* 基础按钮样式 */
.btn {
    display: inline-block;
    padding: 8px 16px;
    border: 1px solid transparent;
    border-radius: 4px;
    font-size: 14px;
    font-weight: 500;
    text-align: center;
    cursor: pointer;
    transition: all 0.2s ease;
    user-select: none;
}

/* 按钮变体 */
.btn-primary {
    background: #007acc;
    color: white;
    border-color: #007acc;
}

.btn-primary:hover {
    background: #005a9e;
    border-color: #005a9e;
}

.btn-primary:pressed {
    background: #004578;
    transform: translateY(1px);
}

.btn-secondary {
    background: #6c757d;
    color: white;
    border-color: #6c757d;
}

.btn-outline {
    background: transparent;
    color: #007acc;
    border-color: #007acc;
}

.btn-outline:hover {
    background: #007acc;
    color: white;
}

/* 按钮尺寸 */
.btn-sm {
    padding: 4px 8px;
    font-size: 12px;
}

.btn-lg {
    padding: 12px 24px;
    font-size: 16px;
}

/* 按钮状态 */
.btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
    pointer-events: none;
}

.btn.loading {
    position: relative;
    color: transparent;
}

.btn.loading::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 16px;
    height: 16px;
    margin: -8px 0 0 -8px;
    border: 2px solid currentColor;
    border-radius: 50%;
    border-top-color: transparent;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

表单组件

/* 表单容器 */
.form-group {
    margin-bottom: 16px;
}

.form-label {
    display: block;
    margin-bottom: 4px;
    font-weight: 500;
    color: #333;
}

/* 输入框样式 */
.form-control {
    display: block;
    width: 100%;
    padding: 8px 12px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 14px;
    transition: border-color 0.2s ease;
}

.form-control:focus {
    outline: none;
    border-color: #007acc;
    box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.2);
}

.form-control:invalid {
    border-color: #dc3545;
}

.form-control:invalid:focus {
    box-shadow: 0 0 0 2px rgba(220, 53, 69, 0.2);
}

/* 选择框样式 */
.form-select {
    display: block;
    width: 100%;
    padding: 8px 32px 8px 12px;
    border: 1px solid #ddd;
    border-radius: 4px;
    background: white url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="none" stroke="%23333" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2 5l6 6 6-6"/></svg>') no-repeat right 8px center;
    background-size: 16px;
    appearance: none;
}

/* 复选框和单选框 */
.form-check {
    display: flex;
    align-items: center;
    margin-bottom: 8px;
}

.form-check-input {
    margin-right: 8px;
}

.form-check-label {
    cursor: pointer;
}

/* 文本域 */
.form-textarea {
    resize: vertical;
    min-height: 80px;
}

/* 表单验证反馈 */
.invalid-feedback {
    display: none;
    color: #dc3545;
    font-size: 12px;
    margin-top: 4px;
}

.form-control:invalid + .invalid-feedback {
    display: block;
}

.valid-feedback {
    display: none;
    color: #28a745;
    font-size: 12px;
    margin-top: 4px;
}

.form-control:valid + .valid-feedback {
    display: block;
}

卡片组件

/* 卡片容器 */
.card {
    background: white;
    border: 1px solid #e0e0e0;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    overflow: hidden;
    transition: box-shadow 0.3s ease;
}

.card:hover {
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}

/* 卡片头部 */
.card-header {
    padding: 16px 20px;
    border-bottom: 1px solid #e0e0e0;
    background: #f8f9fa;
}

.card-title {
    margin: 0;
    font-size: 18px;
    font-weight: 600;
    color: #333;
}

.card-subtitle {
    margin: 4px 0 0 0;
    font-size: 14px;
    color: #666;
}

/* 卡片内容 */
.card-body {
    padding: 20px;
}

.card-text {
    margin-bottom: 16px;
    line-height: 1.5;
    color: #555;
}

/* 卡片底部 */
.card-footer {
    padding: 12px 20px;
    border-top: 1px solid #e0e0e0;
    background: #f8f9fa;
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

/* 卡片图片 */
.card-img {
    width: 100%;
    height: auto;
    display: block;
}

.card-img-top {
    border-radius: 8px 8px 0 0;
}

.card-img-bottom {
    border-radius: 0 0 8px 8px;
}

导航组件

/* 导航栏 */
.navbar {
    display: flex;
    align-items: center;
    padding: 12px 20px;
    background: #fff;
    border-bottom: 1px solid #e0e0e0;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.navbar-brand {
    font-size: 20px;
    font-weight: 700;
    color: #333;
    text-decoration: none;
    margin-right: auto;
}

.navbar-nav {
    display: flex;
    list-style: none;
    margin: 0;
    padding: 0;
    gap: 8px;
}

.nav-item {
    position: relative;
}

.nav-link {
    display: block;
    padding: 8px 16px;
    color: #666;
    text-decoration: none;
    border-radius: 4px;
    transition: all 0.2s ease;
}

.nav-link:hover {
    background: #f0f0f0;
    color: #333;
}

.nav-link.active {
    background: #007acc;
    color: white;
}

/* 下拉菜单 */
.dropdown {
    position: relative;
}

.dropdown-menu {
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 160px;
    background: white;
    border: 1px solid #e0e0e0;
    border-radius: 4px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    z-index: 1000;
    display: none;
}

.dropdown:hover .dropdown-menu {
    display: block;
}

.dropdown-item {
    display: block;
    padding: 8px 16px;
    color: #333;
    text-decoration: none;
    transition: background 0.2s ease;
}

.dropdown-item:hover {
    background: #f0f0f0;
}

.dropdown-divider {
    height: 1px;
    background: #e0e0e0;
    margin: 4px 0;
}

2.4 布局系统

网格系统

/* 容器 */
.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 16px;
}

.container-fluid {
    width: 100%;
    padding: 0 16px;
}

/* 行和列 */
.row {
    display: flex;
    flex-wrap: wrap;
    margin: 0 -8px;
}

.col {
    flex: 1;
    padding: 0 8px;
}

/* 固定列宽 */
.col-1 { flex: 0 0 8.333333%; }
.col-2 { flex: 0 0 16.666667%; }
.col-3 { flex: 0 0 25%; }
.col-4 { flex: 0 0 33.333333%; }
.col-5 { flex: 0 0 41.666667%; }
.col-6 { flex: 0 0 50%; }
.col-7 { flex: 0 0 58.333333%; }
.col-8 { flex: 0 0 66.666667%; }
.col-9 { flex: 0 0 75%; }
.col-10 { flex: 0 0 83.333333%; }
.col-11 { flex: 0 0 91.666667%; }
.col-12 { flex: 0 0 100%; }

/* 响应式列 */
@media (max-width: 768px) {
    .col-sm-12 { flex: 0 0 100%; }
    .col-sm-6 { flex: 0 0 50%; }
}

@media (max-width: 576px) {
    .col-xs-12 { flex: 0 0 100%; }
}

实用工具类

/* 间距工具 */
.m-0 { margin: 0; }
.m-1 { margin: 4px; }
.m-2 { margin: 8px; }
.m-3 { margin: 16px; }
.m-4 { margin: 24px; }
.m-5 { margin: 32px; }

.mt-0 { margin-top: 0; }
.mt-1 { margin-top: 4px; }
.mt-2 { margin-top: 8px; }
.mt-3 { margin-top: 16px; }

.p-0 { padding: 0; }
.p-1 { padding: 4px; }
.p-2 { padding: 8px; }
.p-3 { padding: 16px; }
.p-4 { padding: 24px; }
.p-5 { padding: 32px; }

/* 文本工具 */
.text-left { text-align: left; }
.text-center { text-align: center; }
.text-right { text-align: right; }
.text-justify { text-align: justify; }

.text-primary { color: #007acc; }
.text-secondary { color: #6c757d; }
.text-success { color: #28a745; }
.text-danger { color: #dc3545; }
.text-warning { color: #ffc107; }
.text-info { color: #17a2b8; }
.text-muted { color: #6c757d; }

/* 显示工具 */
.d-none { display: none; }
.d-block { display: block; }
.d-inline { display: inline; }
.d-inline-block { display: inline-block; }
.d-flex { display: flex; }
.d-grid { display: grid; }

/* 弹性布局工具 */
.justify-content-start { justify-content: flex-start; }
.justify-content-end { justify-content: flex-end; }
.justify-content-center { justify-content: center; }
.justify-content-between { justify-content: space-between; }
.justify-content-around { justify-content: space-around; }

.align-items-start { align-items: flex-start; }
.align-items-end { align-items: flex-end; }
.align-items-center { align-items: center; }
.align-items-baseline { align-items: baseline; }
.align-items-stretch { align-items: stretch; }

/* 位置工具 */
.position-static { position: static; }
.position-relative { position: relative; }
.position-absolute { position: absolute; }
.position-fixed { position: fixed; }
.position-sticky { position: sticky; }

/* 浮动工具 */
.float-left { float: left; }
.float-right { float: right; }
.float-none { float: none; }

/* 清除浮动 */
.clearfix::after {
    content: "";
    display: table;
    clear: both;
}

2.5 主题系统

CSS变量定义

/* 主题变量 */
:root {
    /* 颜色系统 */
    --primary-color: #007acc;
    --primary-dark: #005a9e;
    --primary-light: #4da6e0;
    
    --secondary-color: #6c757d;
    --success-color: #28a745;
    --danger-color: #dc3545;
    --warning-color: #ffc107;
    --info-color: #17a2b8;
    
    /* 中性色 */
    --white: #ffffff;
    --gray-100: #f8f9fa;
    --gray-200: #e9ecef;
    --gray-300: #dee2e6;
    --gray-400: #ced4da;
    --gray-500: #adb5bd;
    --gray-600: #6c757d;
    --gray-700: #495057;
    --gray-800: #343a40;
    --gray-900: #212529;
    --black: #000000;
    
    /* 字体系统 */
    --font-family-base: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    --font-family-monospace: 'Consolas', 'Monaco', 'Courier New', monospace;
    
    --font-size-xs: 12px;
    --font-size-sm: 14px;
    --font-size-base: 16px;
    --font-size-lg: 18px;
    --font-size-xl: 20px;
    --font-size-xxl: 24px;
    
    --font-weight-light: 300;
    --font-weight-normal: 400;
    --font-weight-medium: 500;
    --font-weight-semibold: 600;
    --font-weight-bold: 700;
    
    /* 间距系统 */
    --spacing-xs: 4px;
    --spacing-sm: 8px;
    --spacing-md: 16px;
    --spacing-lg: 24px;
    --spacing-xl: 32px;
    --spacing-xxl: 48px;
    
    /* 边框和圆角 */
    --border-width: 1px;
    --border-color: #dee2e6;
    --border-radius-sm: 4px;
    --border-radius: 6px;
    --border-radius-lg: 8px;
    --border-radius-xl: 12px;
    
    /* 阴影 */
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
    --shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    --shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.15);
    --shadow-xl: 0 8px 32px rgba(0, 0, 0, 0.2);
    
    /* 过渡 */
    --transition-fast: 0.15s ease;
    --transition-base: 0.3s ease;
    --transition-slow: 0.5s ease;
}

/* 深色主题 */
[data-theme="dark"] {
    --primary-color: #4da6e0;
    --primary-dark: #007acc;
    --primary-light: #7bc3ea;
    
    --white: #1a1a1a;
    --gray-100: #2d2d2d;
    --gray-200: #3a3a3a;
    --gray-300: #4a4a4a;
    --gray-400: #5a5a5a;
    --gray-500: #6a6a6a;
    --gray-600: #8a8a8a;
    --gray-700: #aaaaaa;
    --gray-800: #cccccc;
    --gray-900: #eeeeee;
    --black: #ffffff;
    
    --border-color: #4a4a4a;
}

主题应用

/* 使用CSS变量 */
.themed-component {
    background: var(--white);
    color: var(--gray-900);
    border: var(--border-width) solid var(--border-color);
    border-radius: var(--border-radius);
    padding: var(--spacing-md);
    font-family: var(--font-family-base);
    font-size: var(--font-size-base);
    box-shadow: var(--shadow);
    transition: var(--transition-base);
}

.themed-button {
    background: var(--primary-color);
    color: var(--white);
    border: none;
    border-radius: var(--border-radius);
    padding: var(--spacing-sm) var(--spacing-md);
    font-weight: var(--font-weight-medium);
    cursor: pointer;
    transition: var(--transition-fast);
}

.themed-button:hover {
    background: var(--primary-dark);
    transform: translateY(-1px);
    box-shadow: var(--shadow-lg);
}

2.6 本章总结

在本章中,我们深入学习了:

HTML扩展

  • Sciter特有的HTML元素和属性
  • 行为属性和状态控制
  • 数据绑定机制

CSS增强

  • 扩展的选择器和属性
  • 流式布局系统
  • 响应式设计技巧

组件系统

  • 常用UI组件的实现
  • 布局系统和网格
  • 实用工具类

主题系统

  • CSS变量的使用
  • 主题切换机制
  • 设计系统构建

2.7 练习题

基础练习

  1. 创建一个响应式的导航栏
  2. 实现一个卡片布局的产品展示页面
  3. 设计一个完整的表单组件
  4. 制作一个可切换的主题系统

进阶练习

  1. 实现一个复杂的网格布局系统
  2. 创建自定义的CSS动画效果
  3. 设计一个模态对话框组件
  4. 实现一个可拖拽的面板布局

挑战练习

  1. 创建一个完整的设计系统
  2. 实现复杂的CSS变换和动画
  3. 设计一个自适应的数据表格
  4. 制作一个交互式的图表组件

下一章预告: 在第3章中,我们将学习TIScript脚本语言,这是Sciter的核心脚本引擎,了解其语法特性、内置对象和API,以及如何编写高效的脚本代码。