You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何实现APP内通过radiobuttons让用户选择全局自定义字体?

嘿,我来帮你搞定这个全局字体选择的单选按钮实现!其实思路特别清晰——核心就是让单选按钮的选择关联到全局样式的切换,同时把用户的选择保存下来,刷新后也能生效。下面分几个主流场景给你具体的实现方案:

原生Web项目(HTML+CSS+JS)

这是最基础的实现方式,适合没有用框架的纯静态项目:

  • 第一步:搭建单选按钮组
    给每个字体选项对应一个单选按钮,统一name属性确保互斥:
<div class="font-selector">
  <label>
    <input type="radio" name="app-font" value="system" checked>
    系统默认字体
  </label>
  <label>
    <input type="radio" name="app-font" value="roboto">
    Roboto
  </label>
  <label>
    <input type="radio" name="app-font" value="montserrat">
    Montserrat
  </label>
</div>
  • 第二步:定义全局字体样式
    先引入需要的自定义字体(这里用公共字体库举例,也可以用本地字体),然后给不同字体定义对应的全局类:
/* 引入外部字体 */
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500&family=Roboto:wght@400;500&display=swap');

/* 定义各字体的全局类 */
.font-system {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
.font-roboto {
  font-family: 'Roboto', sans-serif;
}
.font-montserrat {
  font-family: 'Montserrat', sans-serif;
}

/* 给body默认应用系统字体,加个过渡让切换更丝滑 */
body {
  margin: 0;
  transition: font-family 0.3s ease;
}
  • 第三步:JS监听切换并保存设置
    监听单选按钮的变化,切换body的类名,同时把选择存入localStorage实现持久化:
// 页面加载时恢复之前的选择
document.addEventListener('DOMContentLoaded', () => {
  const savedFont = localStorage.getItem('app-font') || 'system';
  document.body.classList.add(`font-${savedFont}`);
  document.querySelector(`input[name="app-font"][value="${savedFont}"]`).checked = true;
});

// 监听单选按钮的切换事件
document.querySelectorAll('input[name="app-font"]').forEach(radio => {
  radio.addEventListener('change', (e) => {
    const selectedFont = e.target.value;
    // 先移除所有字体类
    document.body.classList.remove('font-system', 'font-roboto', 'font-montserrat');
    // 添加选中的字体类
    document.body.classList.add(`font-${selectedFont}`);
    // 保存到本地存储
    localStorage.setItem('app-font', selectedFont);
  });
});
React项目实现

如果用React,我们可以结合状态管理和useEffect来实现全局切换:

import { useState, useEffect } from 'react';
import './App.css';

function App() {
  // 从localStorage初始化状态,默认用系统字体
  const [selectedFont, setSelectedFont] = useState(localStorage.getItem('app-font') || 'system');

  // 监听字体变化,同步到本地存储和根元素类名
  useEffect(() => {
    localStorage.setItem('app-font', selectedFont);
    const root = document.documentElement;
    root.classList.remove('font-system', 'font-roboto', 'font-montserrat');
    root.classList.add(`font-${selectedFont}`);
  }, [selectedFont]);

  return (
    <div className="App">
      <div className="font-selector">
        <label>
          <input
            type="radio"
            name="app-font"
            value="system"
            checked={selectedFont === 'system'}
            onChange={(e) => setSelectedFont(e.target.value)}
          />
          系统默认字体
        </label>
        <label>
          <input
            type="radio"
            name="app-font"
            value="roboto"
            checked={selectedFont === 'roboto'}
            onChange={(e) => setSelectedFont(e.target.value)}
          />
          Roboto
        </label>
        <label>
          <input
            type="radio"
            name="app-font"
            value="montserrat"
            checked={selectedFont === 'montserrat'}
            onChange={(e) => setSelectedFont(e.target.value)}
          />
          Montserrat
        </label>
      </div>
      {/* 你的应用内容 */}
      <h1>试试切换字体看看效果~</h1>
      <p>这是一段测试文本,全局字体都会跟着变化哦</p>
    </div>
  );
}

export default App;

对应的App.css和原生项目的样式写法一致,这里就不重复啦。

Vue项目实现(Vue3为例)

用Vue的响应式数据结合watch监听,轻松实现全局切换:

<template>
  <div class="app">
    <div class="font-selector">
      <label>
        <input
          type="radio"
          name="app-font"
          value="system"
          v-model="selectedFont"
        />
        系统默认字体
      </label>
      <label>
        <input
          type="radio"
          name="app-font"
          value="roboto"
          v-model="selectedFont"
        />
        Roboto
      </label>
      <label>
        <input
          type="radio"
          name="app-font"
          value="montserrat"
          v-model="selectedFont"
        />
        Montserrat
      </label>
    </div>
    <!-- 应用内容 -->
    <h1>测试全局字体切换</h1>
    <p>这是一段测试文本,看看字体变化效果~</p>
  </div>
</template>

<script setup>
import { ref, watch, onMounted } from 'vue';

// 从localStorage初始化选中的字体
const selectedFont = ref(localStorage.getItem('app-font') || 'system');

// 页面挂载时应用保存的字体
onMounted(() => {
  updateRootFontClass(selectedFont.value);
});

// 监听字体变化,同步到本地存储和根元素
watch(selectedFont, (newFont) => {
  localStorage.setItem('app-font', newFont);
  updateRootFontClass(newFont);
});

// 切换根元素字体类的工具函数
function updateRootFontClass(font) {
  const root = document.documentElement;
  root.classList.remove('font-system', 'font-roboto', 'font-montserrat');
  root.classList.add(`font-${font}`);
}
</script>

<style>
/* 同样引入字体并定义类 */
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500&family=Roboto:wght@400;500&display=swap');

.font-system {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
.font-roboto {
  font-family: 'Roboto', sans-serif;
}
.font-montserrat {
  font-family: 'Montserrat', sans-serif;
}

body {
  transition: font-family 0.3s ease;
}
</style>
额外注意事项
  • 如果用本地自定义字体,记得用@font-face引入:
@font-face {
  font-family: 'MyCustomFont';
  src: url('./fonts/MyCustomFont-Regular.woff2') format('woff2'),
       url('./fonts/MyCustomFont-Regular.woff') format('woff');
  font-weight: normal;
  font-style: normal;
}
  • 确保你的组件不要写死font-family,让字体样式继承自body或根元素,这样切换类名时才能全局生效。
  • 可以给单选按钮加些自定义样式,让它更贴合你的应用UI,比如隐藏原生radio,用自定义图标代替。

内容的提问来源于stack exchange,提问作者user10990943

火山引擎 最新活动