Skip to content

现代 CSS 框架对比

在现代前端开发中,CSS框架已成为提高开发效率和保证设计一致性的重要工具。本文将深入对比当前最流行的CSS框架,帮助你为项目选择最合适的解决方案。

🎯 框架概览

主流CSS框架分类

mermaid
graph TD
    A[CSS框架] --> B[组件框架]
    A --> C[实用工具框架]
    A --> D[混合框架]
    
    B --> E[Bootstrap]
    B --> F[Bulma]
    B --> G[Foundation]
    
    C --> H[Tailwind CSS]
    C --> I[Tachyons]
    
    D --> J[UIKit]
    D --> K[Semantic UI]

🚀 Tailwind CSS

核心理念

Tailwind CSS 采用"实用工具优先"的方法,提供低级别的实用工具类来构建自定义设计。

html
<!-- Tailwind CSS 示例 -->
<div class="max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden md:max-w-2xl">
  <div class="md:flex">
    <div class="md:shrink-0">
      <img class="h-48 w-full object-cover md:h-full md:w-48" 
           src="/img/building.jpg" alt="Modern building architecture">
    </div>
    <div class="p-8">
      <div class="uppercase tracking-wide text-sm text-indigo-500 font-semibold">
        Company retreats
      </div>
      <a href="#" class="block mt-1 text-lg leading-tight font-medium text-black hover:underline">
        Incredible accommodation for your team
      </a>
      <p class="mt-2 text-slate-500">
        Looking to take your team away on a retreat to enjoy awesome food and take in some sunshine? 
        We have a list of places to do just that.
      </p>
    </div>
  </div>
</div>

优势分析

javascript
// Tailwind 配置示例
module.exports = {
  content: ['./src/**/*.{html,js,vue,jsx,tsx}'],
  theme: {
    extend: {
      colors: {
        'brand-blue': '#1fb6ff',
        'brand-purple': '#7e5bef',
        'brand-pink': '#ff49db',
        'brand-orange': '#ff7849',
        'brand-green': '#13ce66',
        'brand-yellow': '#ffc82c',
        'brand-gray-dark': '#273444',
        'brand-gray': '#8492a6',
        'brand-gray-light': '#d3dce6',
      },
      fontFamily: {
        'sans': ['Inter', 'system-ui', 'sans-serif'],
        'serif': ['Georgia', 'serif'],
      },
      spacing: {
        '128': '32rem',
        '144': '36rem',
      },
      borderRadius: {
        '4xl': '2rem',
      }
    }
  },
  plugins: [
    require('@tailwindcss/forms'),
    require('@tailwindcss/typography'),
    require('@tailwindcss/aspect-ratio'),
  ]
}

性能优化

css
/* 生产环境优化后的CSS大小对比 */
/* 传统CSS框架 */
.traditional-framework {
  /* Bootstrap 5: ~200KB */
  /* Bulma: ~180KB */
}

/* Tailwind CSS (优化后) */
.tailwind-optimized {
  /* 通常只有 10-50KB */
  /* 只包含实际使用的类 */
}

自定义组件抽象

css
/* 使用 @apply 指令创建组件 */
@layer components {
  .btn-primary {
    @apply py-2 px-4 bg-blue-500 text-white font-semibold rounded-lg shadow-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-opacity-75;
  }
  
  .card {
    @apply bg-white shadow-lg rounded-lg overflow-hidden;
  }
  
  .card-header {
    @apply px-6 py-4 bg-gray-50 border-b border-gray-200;
  }
  
  .card-body {
    @apply px-6 py-4;
  }
}

🎨 Bootstrap

组件生态系统

html
<!-- Bootstrap 5 组件示例 -->
<div class="container">
  <div class="row">
    <div class="col-md-8">
      <div class="card">
        <div class="card-header">
          <ul class="nav nav-tabs card-header-tabs">
            <li class="nav-item">
              <a class="nav-link active" href="#home">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#profile">Profile</a>
            </li>
          </ul>
        </div>
        <div class="card-body">
          <h5 class="card-title">Special title treatment</h5>
          <p class="card-text">With supporting text below as a natural lead-in to additional content.</p>
          <a href="#" class="btn btn-primary">Go somewhere</a>
        </div>
      </div>
    </div>
    <div class="col-md-4">
      <div class="list-group">
        <a href="#" class="list-group-item list-group-item-action active">
          Cras justo odio
        </a>
        <a href="#" class="list-group-item list-group-item-action">Dapibus ac facilisis in</a>
        <a href="#" class="list-group-item list-group-item-action">Morbi leo risus</a>
      </div>
    </div>
  </div>
</div>

自定义主题

scss
// Bootstrap 自定义变量
$primary: #007bff;
$secondary: #6c757d;
$success: #28a745;
$info: #17a2b8;
$warning: #ffc107;
$danger: #dc3545;
$light: #f8f9fa;
$dark: #343a40;

// 自定义字体
$font-family-sans-serif: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto;

// 自定义断点
$grid-breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px,
  xxl: 1400px
);

// 导入Bootstrap
@import "~bootstrap/scss/bootstrap";

// 自定义组件
.custom-navbar {
  background: linear-gradient(135deg, $primary 0%, darken($primary, 20%) 100%);
  
  .navbar-brand {
    font-weight: 700;
    font-size: 1.5rem;
  }
}

.custom-card {
  border: none;
  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
  transition: transform 0.2s ease-in-out;
  
  &:hover {
    transform: translateY(-2px);
  }
}

JavaScript 集成

javascript
// Bootstrap 5 JavaScript 组件
import { Modal, Tooltip, Popover } from 'bootstrap';

class BootstrapComponents {
  constructor() {
    this.initializeComponents();
  }
  
  initializeComponents() {
    // 初始化所有工具提示
    const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
    tooltipTriggerList.map(tooltipTriggerEl => new Tooltip(tooltipTriggerEl));
    
    // 初始化所有弹出框
    const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'));
    popoverTriggerList.map(popoverTriggerEl => new Popover(popoverTriggerEl));
  }
  
  showModal(modalId, options = {}) {
    const modalElement = document.getElementById(modalId);
    const modal = new Modal(modalElement, options);
    modal.show();
    return modal;
  }
  
  createDynamicModal(title, content, actions = []) {
    const modalHTML = `
      <div class="modal fade" id="dynamicModal" tabindex="-1">
        <div class="modal-dialog">
          <div class="modal-content">
            <div class="modal-header">
              <h5 class="modal-title">${title}</h5>
              <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
              ${content}
            </div>
            <div class="modal-footer">
              ${actions.map(action => `
                <button type="button" class="btn ${action.class}" ${action.dismiss ? 'data-bs-dismiss="modal"' : ''}>
                  ${action.text}
                </button>
              `).join('')}
            </div>
          </div>
        </div>
      </div>
    `;
    
    document.body.insertAdjacentHTML('beforeend', modalHTML);
    return this.showModal('dynamicModal');
  }
}

// 使用示例
const bootstrap = new BootstrapComponents();

// 创建动态模态框
bootstrap.createDynamicModal(
  'Confirm Action',
  'Are you sure you want to proceed?',
  [
    { text: 'Cancel', class: 'btn-secondary', dismiss: true },
    { text: 'Confirm', class: 'btn-primary' }
  ]
);

💎 Bulma

现代CSS特性

html
<!-- Bulma 纯CSS框架示例 -->
<section class="hero is-primary is-medium">
  <div class="hero-body">
    <div class="container">
      <h1 class="title">
        Primary hero
      </h1>
      <h2 class="subtitle">
        Primary subtitle
      </h2>
    </div>
  </div>
</section>

<section class="section">
  <div class="container">
    <div class="columns">
      <div class="column is-8">
        <div class="content">
          <h2>Main Content</h2>
          <p>This is the main content area.</p>
        </div>
      </div>
      <div class="column is-4">
        <aside class="menu">
          <p class="menu-label">General</p>
          <ul class="menu-list">
            <li><a class="is-active">Dashboard</a></li>
            <li><a>Customers</a></li>
          </ul>
        </aside>
      </div>
    </div>
  </div>
</section>

Flexbox 布局系统

scss
// Bulma 自定义变量
$primary: hsl(171, 100%, 41%);
$link: hsl(229, 53%, 53%);
$info: hsl(204, 86%, 53%);
$success: hsl(141, 53%, 53%);
$warning: hsl(48, 100%, 67%);
$danger: hsl(348, 100%, 61%);

// 自定义字体
$family-primary: 'Inter', BlinkMacSystemFont, -apple-system, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;

// 导入Bulma
@import "~bulma/bulma";

// 自定义组件
.custom-hero {
  background: linear-gradient(135deg, $primary 0%, darken($primary, 20%) 100%);
  
  .hero-body {
    padding: 6rem 1.5rem;
  }
}

.custom-card {
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
  transition: all 0.3s ease;
  
  &:hover {
    transform: translateY(-4px);
    box-shadow: 0 12px 48px rgba(0, 0, 0, 0.15);
  }
}

响应式修饰符

html
<!-- Bulma 响应式类 -->
<div class="columns is-mobile">
  <div class="column is-half-mobile is-one-third-tablet is-one-quarter-desktop">
    <div class="box">
      <p class="is-size-7-mobile is-size-6-tablet is-size-5-desktop">
        Responsive text size
      </p>
    </div>
  </div>
</div>

<!-- 显示/隐藏修饰符 -->
<div class="is-hidden-mobile is-visible-tablet">
  Only visible on tablet and above
</div>

<div class="is-hidden-desktop">
  Hidden on desktop
</div>

🏗️ Foundation

高级网格系统

html
<!-- Foundation XY Grid -->
<div class="grid-container">
  <div class="grid-x grid-padding-x">
    <div class="large-8 medium-8 small-12 cell">
      <div class="primary callout">
        <p>Main content area with responsive sizing</p>
      </div>
    </div>
    <div class="large-4 medium-4 small-12 cell">
      <div class="secondary callout">
        <p>Sidebar content</p>
      </div>
    </div>
  </div>
  
  <!-- 复杂布局 -->
  <div class="grid-x grid-padding-x align-center">
    <div class="large-6 medium-8 small-10 cell">
      <div class="grid-x grid-padding-x">
        <div class="large-6 cell">
          <div class="success callout">Nested 1</div>
        </div>
        <div class="large-6 cell">
          <div class="warning callout">Nested 2</div>
        </div>
      </div>
    </div>
  </div>
</div>

可访问性特性

javascript
// Foundation JavaScript 组件
import { Foundation } from 'foundation-sites';

class FoundationAccessibility {
  constructor() {
    Foundation.addToJquery($);
    this.initializeComponents();
  }
  
  initializeComponents() {
    // 初始化所有Foundation组件
    $(document).foundation();
    
    // 自定义可访问性增强
    this.enhanceAccessibility();
  }
  
  enhanceAccessibility() {
    // 为所有按钮添加ARIA标签
    $('button:not([aria-label]):not([aria-labelledby])').each(function() {
      const text = $(this).text().trim();
      if (text) {
        $(this).attr('aria-label', text);
      }
    });
    
    // 为表单字段添加必要的ARIA属性
    $('input[required], select[required], textarea[required]').attr('aria-required', 'true');
    
    // 增强导航可访问性
    $('[data-dropdown-menu]').attr('role', 'menubar');
    $('[data-dropdown-menu] li').attr('role', 'none');
    $('[data-dropdown-menu] a').attr('role', 'menuitem');
  }
  
  // 创建可访问的模态框
  createAccessibleModal(id, title, content) {
    const modalHTML = `
      <div class="reveal" id="${id}" data-reveal 
           role="dialog" aria-labelledby="${id}-title" aria-describedby="${id}-content">
        <h2 id="${id}-title">${title}</h2>
        <div id="${id}-content">
          ${content}
        </div>
        <button class="close-button" data-close aria-label="Close modal" type="button">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
    `;
    
    $('body').append(modalHTML);
    $(`#${id}`).foundation();
    return $(`#${id}`);
  }
}

// 使用示例
const foundationApp = new FoundationAccessibility();

// 创建可访问的模态框
foundationApp.createAccessibleModal(
  'accessibleModal',
  'Important Information',
  '<p>This modal is fully accessible with proper ARIA attributes.</p>'
);

📊 性能对比分析

包大小对比

javascript
// 各框架的包大小分析
const frameworkSizes = {
  tailwind: {
    development: '3.2MB', // 包含所有类
    production: '10-50KB', // 仅包含使用的类
    gzipped: '3-15KB'
  },
  bootstrap: {
    css: '160KB',
    js: '60KB',
    gzipped: '25KB (CSS) + 20KB (JS)'
  },
  bulma: {
    css: '180KB',
    gzipped: '25KB'
  },
  foundation: {
    css: '140KB',
    js: '85KB',
    gzipped: '20KB (CSS) + 25KB (JS)'
  }
};

// 性能测试工具
class FrameworkPerformanceTest {
  constructor() {
    this.metrics = {};
  }
  
  async measureLoadTime(frameworkName, cssUrl, jsUrl = null) {
    const startTime = performance.now();
    
    try {
      // 加载CSS
      await this.loadCSS(cssUrl);
      
      // 加载JavaScript(如果有)
      if (jsUrl) {
        await this.loadJS(jsUrl);
      }
      
      const endTime = performance.now();
      const loadTime = endTime - startTime;
      
      this.metrics[frameworkName] = {
        loadTime: loadTime,
        cssSize: await this.getResourceSize(cssUrl),
        jsSize: jsUrl ? await this.getResourceSize(jsUrl) : 0
      };
      
      return this.metrics[frameworkName];
    } catch (error) {
      console.error(`Failed to load ${frameworkName}:`, error);
      return null;
    }
  }
  
  loadCSS(url) {
    return new Promise((resolve, reject) => {
      const link = document.createElement('link');
      link.rel = 'stylesheet';
      link.href = url;
      link.onload = resolve;
      link.onerror = reject;
      document.head.appendChild(link);
    });
  }
  
  loadJS(url) {
    return new Promise((resolve, reject) => {
      const script = document.createElement('script');
      script.src = url;
      script.onload = resolve;
      script.onerror = reject;
      document.head.appendChild(script);
    });
  }
  
  async getResourceSize(url) {
    try {
      const response = await fetch(url, { method: 'HEAD' });
      return response.headers.get('content-length') || 'Unknown';
    } catch {
      return 'Unknown';
    }
  }
  
  generateReport() {
    console.table(this.metrics);
    
    // 找出最快的框架
    const fastest = Object.entries(this.metrics)
      .sort(([,a], [,b]) => a.loadTime - b.loadTime)[0];
    
    console.log(`🏆 Fastest loading framework: ${fastest[0]} (${fastest[1].loadTime.toFixed(2)}ms)`);
  }
}

运行时性能

javascript
// CSS选择器性能测试
class CSSPerformanceTest {
  constructor() {
    this.testResults = {};
  }
  
  // 测试不同框架的选择器性能
  testSelectorPerformance() {
    const selectors = {
      tailwind: [
        '.flex.items-center.justify-between',
        '.bg-blue-500.hover\\:bg-blue-700',
        '.text-sm.font-medium.text-gray-900'
      ],
      bootstrap: [
        '.d-flex.align-items-center.justify-content-between',
        '.btn.btn-primary',
        '.text-muted.small'
      ],
      bulma: [
        '.is-flex.is-align-items-center.is-justify-content-space-between',
        '.button.is-primary',
        '.has-text-grey.is-size-7'
      ]
    };
    
    Object.entries(selectors).forEach(([framework, selectorList]) => {
      const startTime = performance.now();
      
      selectorList.forEach(selector => {
        // 执行1000次查询
        for (let i = 0; i < 1000; i++) {
          document.querySelectorAll(selector);
        }
      });
      
      const endTime = performance.now();
      this.testResults[framework] = endTime - startTime;
    });
    
    return this.testResults;
  }
  
  // 测试样式计算性能
  testStyleCalculation() {
    const testElement = document.createElement('div');
    document.body.appendChild(testElement);
    
    const frameworks = {
      tailwind: 'flex items-center justify-center p-4 m-2 bg-blue-500 text-white rounded-lg shadow-md hover:bg-blue-700 transition-colors duration-200',
      bootstrap: 'd-flex align-items-center justify-content-center p-3 m-2 bg-primary text-white rounded shadow',
      bulma: 'is-flex is-align-items-center is-justify-content-center p-4 m-2 has-background-primary has-text-white'
    };
    
    const results = {};
    
    Object.entries(frameworks).forEach(([framework, classes]) => {
      const startTime = performance.now();
      
      // 应用和移除类1000次
      for (let i = 0; i < 1000; i++) {
        testElement.className = classes;
        getComputedStyle(testElement); // 强制样式计算
        testElement.className = '';
      }
      
      const endTime = performance.now();
      results[framework] = endTime - startTime;
    });
    
    document.body.removeChild(testElement);
    return results;
  }
}

🎯 选择指南

决策矩阵

javascript
// 框架选择决策工具
class FrameworkSelector {
  constructor() {
    this.criteria = {
      learningCurve: { weight: 0.2 },
      customization: { weight: 0.25 },
      performance: { weight: 0.2 },
      ecosystem: { weight: 0.15 },
      maintenance: { weight: 0.1 },
      accessibility: { weight: 0.1 }
    };
    
    this.frameworks = {
      tailwind: {
        learningCurve: 7, // 1-10, 10最容易
        customization: 10,
        performance: 9,
        ecosystem: 8,
        maintenance: 8,
        accessibility: 7
      },
      bootstrap: {
        learningCurve: 9,
        customization: 6,
        performance: 7,
        ecosystem: 10,
        maintenance: 9,
        accessibility: 8
      },
      bulma: {
        learningCurve: 8,
        customization: 7,
        performance: 8,
        ecosystem: 6,
        maintenance: 7,
        accessibility: 7
      },
      foundation: {
        learningCurve: 6,
        customization: 8,
        performance: 7,
        ecosystem: 7,
        maintenance: 6,
        accessibility: 9
      }
    };
  }
  
  calculateScore(framework) {
    const scores = this.frameworks[framework];
    let totalScore = 0;
    
    Object.entries(this.criteria).forEach(([criterion, { weight }]) => {
      totalScore += scores[criterion] * weight;
    });
    
    return totalScore;
  }
  
  recommend(projectRequirements = {}) {
    // 根据项目需求调整权重
    if (projectRequirements.highCustomization) {
      this.criteria.customization.weight = 0.4;
      this.criteria.learningCurve.weight = 0.1;
    }
    
    if (projectRequirements.rapidPrototyping) {
      this.criteria.learningCurve.weight = 0.3;
      this.criteria.ecosystem.weight = 0.25;
    }
    
    if (projectRequirements.accessibility) {
      this.criteria.accessibility.weight = 0.25;
    }
    
    // 计算所有框架的得分
    const scores = {};
    Object.keys(this.frameworks).forEach(framework => {
      scores[framework] = this.calculateScore(framework);
    });
    
    // 排序并返回推荐
    const sorted = Object.entries(scores)
      .sort(([,a], [,b]) => b - a)
      .map(([framework, score]) => ({ framework, score: score.toFixed(2) }));
    
    return {
      recommendation: sorted[0].framework,
      scores: sorted,
      reasoning: this.generateReasoning(sorted[0].framework, projectRequirements)
    };
  }
  
  generateReasoning(framework, requirements) {
    const reasons = {
      tailwind: [
        '高度可定制,适合独特设计需求',
        '优秀的性能表现,生产环境包体积小',
        '现代化的开发体验'
      ],
      bootstrap: [
        '成熟的生态系统和丰富的组件',
        '学习曲线平缓,团队容易上手',
        '广泛的社区支持和第三方资源'
      ],
      bulma: [
        '现代CSS特性,无JavaScript依赖',
        '简洁的语法和良好的可读性',
        '基于Flexbox的响应式设计'
      ],
      foundation: [
        '出色的可访问性支持',
        '灵活的网格系统',
        '适合复杂的企业级应用'
      ]
    };
    
    return reasons[framework] || ['综合表现良好'];
  }
}

// 使用示例
const selector = new FrameworkSelector();

// 为高定制化项目推荐框架
const recommendation = selector.recommend({
  highCustomization: true,
  accessibility: true
});

console.log('推荐框架:', recommendation.recommendation);
console.log('推荐理由:', recommendation.reasoning);
console.log('详细评分:', recommendation.scores);

🔄 迁移策略

从Bootstrap到Tailwind

javascript
// Bootstrap到Tailwind的类映射
const bootstrapToTailwind = {
  // 布局
  'container': 'container mx-auto',
  'container-fluid': 'w-full',
  'row': 'flex flex-wrap',
  'col': 'flex-1',
  'col-12': 'w-full',
  'col-6': 'w-1/2',
  'col-4': 'w-1/3',
  'col-3': 'w-1/4',
  
  // 间距
  'p-0': 'p-0',
  'p-1': 'p-1',
  'p-2': 'p-2',
  'p-3': 'p-3',
  'p-4': 'p-4',
  'p-5': 'p-6',
  'm-0': 'm-0',
  'm-1': 'm-1',
  'm-2': 'm-2',
  'm-3': 'm-3',
  'm-4': 'm-4',
  'm-5': 'm-6',
  
  // 显示
  'd-none': 'hidden',
  'd-block': 'block',
  'd-inline': 'inline',
  'd-inline-block': 'inline-block',
  'd-flex': 'flex',
  
  // Flexbox
  'justify-content-start': 'justify-start',
  'justify-content-center': 'justify-center',
  'justify-content-end': 'justify-end',
  'justify-content-between': 'justify-between',
  'align-items-start': 'items-start',
  'align-items-center': 'items-center',
  'align-items-end': 'items-end',
  
  // 文本
  'text-left': 'text-left',
  'text-center': 'text-center',
  'text-right': 'text-right',
  'text-muted': 'text-gray-500',
  'text-primary': 'text-blue-600',
  'text-success': 'text-green-600',
  'text-danger': 'text-red-600',
  'text-warning': 'text-yellow-600',
  
  // 背景
  'bg-primary': 'bg-blue-600',
  'bg-secondary': 'bg-gray-600',
  'bg-success': 'bg-green-600',
  'bg-danger': 'bg-red-600',
  'bg-warning': 'bg-yellow-600',
  'bg-light': 'bg-gray-100',
  'bg-dark': 'bg-gray-800',
  
  // 按钮
  'btn': 'px-4 py-2 rounded font-medium',
  'btn-primary': 'bg-blue-600 text-white hover:bg-blue-700',
  'btn-secondary': 'bg-gray-600 text-white hover:bg-gray-700',
  'btn-success': 'bg-green-600 text-white hover:bg-green-700',
  'btn-danger': 'bg-red-600 text-white hover:bg-red-700',
  'btn-lg': 'px-6 py-3 text-lg',
  'btn-sm': 'px-3 py-1 text-sm'
};

// 自动迁移工具
class BootstrapToTailwindMigrator {
  constructor() {
    this.mapping = bootstrapToTailwind;
    this.migrationLog = [];
  }
  
  migrateHTML(htmlContent) {
    let migratedHTML = htmlContent;
    
    Object.entries(this.mapping).forEach(([bootstrap, tailwind]) => {
      const regex = new RegExp(`\\b${bootstrap}\\b`, 'g');
      const matches = migratedHTML.match(regex);
      
      if (matches) {
        migratedHTML = migratedHTML.replace(regex, tailwind);
        this.migrationLog.push({
          from: bootstrap,
          to: tailwind,
          occurrences: matches.length
        });
      }
    });
    
    return {
      html: migratedHTML,
      log: this.migrationLog
    };
  }
  
  generateMigrationReport() {
    console.group('🔄 Bootstrap to Tailwind Migration Report');
    this.migrationLog.forEach(entry => {
      console.log(`${entry.from} → ${entry.to} (${entry.occurrences} occurrences)`);
    });
    console.groupEnd();
  }
}

// 使用示例
const migrator = new BootstrapToTailwindMigrator();

const bootstrapHTML = `
<div class="container">
  <div class="row">
    <div class="col-6">
      <button class="btn btn-primary btn-lg">Click me</button>
    </div>
  </div>
</div>
`;

const result = migrator.migrateHTML(bootstrapHTML);
console.log('Migrated HTML:', result.html);
migrator.generateMigrationReport();

🛠️ 实际项目案例

电商网站案例

html
<!-- Tailwind CSS 实现 -->
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
  <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
    <div class="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition-shadow duration-300">
      <img class="w-full h-48 object-cover" src="product.jpg" alt="Product">
      <div class="p-4">
        <h3 class="text-lg font-semibold text-gray-900 mb-2">Product Name</h3>
        <p class="text-gray-600 text-sm mb-3">Product description here...</p>
        <div class="flex items-center justify-between">
          <span class="text-2xl font-bold text-blue-600">$99.99</span>
          <button class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 transition-colors">
            Add to Cart
          </button>
        </div>
      </div>
    </div>
  </div>
</div>

<!-- Bootstrap 实现 -->
<div class="container">
  <div class="row">
    <div class="col-lg-3 col-md-6 mb-4">
      <div class="card h-100 shadow-sm">
        <img class="card-img-top" src="product.jpg" alt="Product">
        <div class="card-body d-flex flex-column">
          <h5 class="card-title">Product Name</h5>
          <p class="card-text text-muted">Product description here...</p>
          <div class="mt-auto d-flex justify-content-between align-items-center">
            <h4 class="text-primary mb-0">$99.99</h4>
            <button class="btn btn-primary">Add to Cart</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

管理后台案例

html
<!-- Bulma 实现 -->
<div class="columns is-fullheight">
  <div class="column is-2 is-sidebar-menu is-hidden-mobile">
    <aside class="menu">
      <p class="menu-label">General</p>
      <ul class="menu-list">
        <li><a class="is-active">Dashboard</a></li>
        <li><a>Customers</a></li>
        <li><a>Orders</a></li>
      </ul>
    </aside>
  </div>
  
  <div class="column">
    <nav class="navbar" role="navigation">
      <div class="navbar-brand">
        <a class="navbar-item">
          <strong>Admin Panel</strong>
        </a>
      </div>
      <div class="navbar-menu">
        <div class="navbar-end">
          <div class="navbar-item has-dropdown is-hoverable">
            <a class="navbar-link">Account</a>
            <div class="navbar-dropdown">
              <a class="navbar-item">Profile</a>
              <a class="navbar-item">Settings</a>
              <hr class="navbar-divider">
              <a class="navbar-item">Logout</a>
            </div>
          </div>
        </div>
      </div>
    </nav>
    
    <section class="section">
      <div class="container">
        <div class="columns">
          <div class="column is-3">
            <div class="box has-text-centered">
              <p class="title">1,234</p>
              <p class="subtitle">Total Users</p>
            </div>
          </div>
          <div class="column is-3">
            <div class="box has-text-centered">
              <p class="title">567</p>
              <p class="subtitle">Orders Today</p>
            </div>
          </div>
        </div>
      </div>
    </section>
  </div>
</div>

📈 趋势与未来

CSS-in-JS vs CSS框架

javascript
// Styled Components 示例
import styled from 'styled-components';

const Card = styled.div`
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  padding: 1.5rem;
  transition: transform 0.2s ease;
  
  &:hover {
    transform: translateY(-2px);
  }
  
  @media (max-width: 768px) {
    padding: 1rem;
  }
`;

// Emotion 示例
import { css } from '@emotion/react';

const cardStyle = css`
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  padding: 1.5rem;
  
  &:hover {
    transform: translateY(-2px);
  }
`;

// 对比分析
const comparisonMatrix = {
  cssFrameworks: {
    pros: [
      '学习曲线平缓',
      '社区资源丰富',
      '跨项目复用性强',
      '设计系统一致性'
    ],
    cons: [
      '定制化程度有限',
      '可能存在冗余代码',
      '样式覆盖复杂'
    ]
  },
  cssInJs: {
    pros: [
      '完全的样式隔离',
      '动态样式支持',
      '与组件逻辑紧密结合',
      '类型安全(TypeScript)'
    ],
    cons: [
      '运行时性能开销',
      '学习成本较高',
      '调试相对困难'
    ]
  }
};

新兴技术趋势

css
/* CSS Container Queries */
.card-container {
  container-type: inline-size;
}

@container (min-width: 300px) {
  .card {
    display: flex;
    flex-direction: row;
  }
}

/* CSS Cascade Layers */
@layer reset, base, components, utilities;

@layer base {
  h1 {
    font-size: 2rem;
    font-weight: bold;
  }
}

@layer components {
  .btn {
    padding: 0.5rem 1rem;
    border-radius: 0.25rem;
    border: none;
    cursor: pointer;
  }
}

/* CSS Nesting (原生支持) */
.card {
  background: white;
  border-radius: 8px;
  
  & .title {
    font-size: 1.25rem;
    font-weight: 600;
    
    &:hover {
      color: blue;
    }
  }
  
  & .content {
    margin-top: 1rem;
    
    & p {
      line-height: 1.6;
    }
  }
}

🎯 最终推荐

项目类型推荐

javascript
const projectRecommendations = {
  startup: {
    framework: 'Tailwind CSS',
    reason: '快速原型开发,高度定制化,小团队易于维护',
    alternatives: ['Bootstrap(如果团队经验不足)']
  },
  
  enterprise: {
    framework: 'Bootstrap',
    reason: '成熟稳定,丰富的组件库,大团队协作友好',
    alternatives: ['Foundation(如果需要更好的可访问性)']
  },
  
  designSystem: {
    framework: 'Tailwind CSS',
    reason: '设计令牌系统,高度可定制,与设计工具集成良好',
    alternatives: ['自定义CSS框架']
  },
  
  rapidPrototyping: {
    framework: 'Bootstrap',
    reason: '开箱即用的组件,快速搭建界面',
    alternatives: ['Bulma(如果不需要JavaScript)']
  },
  
  modernWebApp: {
    framework: 'Tailwind CSS',
    reason: '现代化开发体验,优秀的性能表现',
    alternatives: ['CSS-in-JS(如果使用React生态)']
  },
  
  accessibilityFirst: {
    framework: 'Foundation',
    reason: '内置可访问性支持,符合WCAG标准',
    alternatives: ['Bootstrap + 可访问性增强']
  }
};

// 智能推荐函数
function recommendFramework(projectInfo) {
  const {
    teamSize,
    timeline,
    customizationNeeds,
    accessibilityRequirements,
    performanceRequirements,
    maintenanceTeam
  } = projectInfo;
  
  let score = {
    tailwind: 0,
    bootstrap: 0,
    bulma: 0,
    foundation: 0
  };
  
  // 团队规模影响
  if (teamSize === 'small') {
    score.tailwind += 2;
    score.bulma += 1;
  } else if (teamSize === 'large') {
    score.bootstrap += 2;
    score.foundation += 1;
  }
  
  // 时间线影响
  if (timeline === 'tight') {
    score.bootstrap += 2;
    score.bulma += 1;
  } else if (timeline === 'flexible') {
    score.tailwind += 2;
  }
  
  // 定制化需求
  if (customizationNeeds === 'high') {
    score.tailwind += 3;
  } else if (customizationNeeds === 'low') {
    score.bootstrap += 2;
    score.bulma += 1;
  }
  
  // 可访问性要求
  if (accessibilityRequirements === 'high') {
    score.foundation += 3;
    score.bootstrap += 1;
  }
  
  // 性能要求
  if (performanceRequirements === 'high') {
    score.tailwind += 2;
    score.bulma += 1;
  }
  
  // 找出得分最高的框架
  const recommended = Object.entries(score)
    .sort(([,a], [,b]) => b - a)[0][0];
  
  return {
    recommended,
    scores: score,
    reasoning: generateRecommendationReasoning(recommended, projectInfo)
  };
}

function generateRecommendationReasoning(framework, projectInfo) {
  const reasons = {
    tailwind: [
      '提供最大的设计灵活性',
      '优秀的性能表现',
      '现代化的开发体验',
      '适合小团队快速迭代'
    ],
    bootstrap: [
      '成熟稳定的解决方案',
      '丰富的组件生态',
      '团队学习成本低',
      '适合快速原型开发'
    ],
    bulma: [
      '现代CSS特性',
      '无JavaScript依赖',
      '简洁的语法',
      '适合中小型项目'
    ],
    foundation: [
      '出色的可访问性支持',
      '灵活的网格系统',
      '适合企业级应用',
      '符合Web标准'
    ]
  };
  
  return reasons[framework] || [];
}

// 使用示例
const projectInfo = {
  teamSize: 'small',
  timeline: 'flexible',
  customizationNeeds: 'high',
  accessibilityRequirements: 'medium',
  performanceRequirements: 'high',
  maintenanceTeam: 'experienced'
};

const recommendation = recommendFramework(projectInfo);
console.log('推荐框架:', recommendation.recommended);
console.log('推荐理由:', recommendation.reasoning);

📚 学习资源

官方文档

实用工具

在线编辑器

总结

选择CSS框架需要综合考虑项目需求、团队能力和长期维护成本。没有完美的框架,只有最适合的选择:

  1. Tailwind CSS:适合追求高度定制化和现代开发体验的项目
  2. Bootstrap:适合需要快速开发和丰富组件的项目
  3. Bulma:适合喜欢现代CSS特性且不需要JavaScript的项目
  4. Foundation:适合对可访问性有高要求的企业级项目

记住,框架只是工具,关键是要理解CSS基础原理,这样才能在任何框架中都游刃有余。

vitepress开发指南