Tailwind CSS peer-checked样式在Chrome和Safari中无法正常生效
解决Svelte+Tailwind单选开关在Chrome/Safari中样式失效问题
问题描述
我使用Svelte开发了一个双选项单选开关,核心代码如下:
<div class="flex justify-center mt-3 mb-2"> <div class="inline-flex outline outline-neutral-100 rounded-md"> <div> <input type="radio" name="radio" id="internato" class="sr-only peer" checked on:click={() => { $spotTypeBeforeAPICall = spotTypes.INTERNATO; }} /> <label for="internato" class="cursor-pointer inline-flex items-center py-2 px-3 text-base sm:text-lg peer-checked:bg-neutral-100 peer-checked:text-cyan-900 peer-checked:font-bold hover:font-bold" > IFE </label> </div> <div> <input type="radio" name="radio" id="iac" class="sr-only peer" on:click={() => { $spotTypeBeforeAPICall = spotTypes.IAC; }} /> <label for="iac" class="cursor-pointer inline-flex items-center py-2 px-3 text-base sm:text-lg peer-checked:bg-neutral-100 peer-checked:text-cyan-900 peer-checked:font-bold hover:font-bold" > IAC </label> </div> </div> </div>
该组件在Firefox中显示正常:选中的选项会呈现灰色背景、深蓝色加粗文字;但在Chrome和Safari中,选中后的peer-checked样式完全不生效。
相关配置文件如下:
tailwind.config.js
/** @type {import('tailwindcss').Config} */ export default { content: ["./src/**/*.{html,js,svelte}"], theme: { extend: {}, }, plugins: [], }
rollup.config.js
import { spawn } from 'child_process'; import svelte from 'rollup-plugin-svelte'; import commonjs from '@rollup/plugin-commonjs'; import terser from '@rollup/plugin-terser'; import resolve from '@rollup/plugin-node-resolve'; import livereload from 'rollup-plugin-livereload'; import css from 'rollup-plugin-css-only'; const production = !process.env.ROLLUP_WATCH; function serve() { let server; function toExit() { if (server) server.kill(0); } return { writeBundle() { if (server) return; server = spawn('npm', ['run', 'start', '--', '--dev'], { stdio: ['ignore', 'inherit', 'inherit'], shell: true }); process.on('SIGTERM', toExit); process.on('exit', toExit); } }; } export default { input: 'public/main.js', output: { sourcemap: true, format: 'iife', name: 'app', file: 'public/build/bundle.js' }, plugins: [ svelte({ compilerOptions: { // enable run-time checks when not in production dev: !production } }), // we'll extract any component CSS out into // a separate file - better for performance css({ output: 'bundle.css' }), // If you have external dependencies installed from // npm, you'll most likely need these plugins. In // some cases you'll need additional configuration - // consult the documentation for details: // https://github.com/rollup/plugins/tree/master/packages/commonjs resolve({ browser: true, dedupe: ['svelte'], exportConditions: ['svelte'] }), commonjs(), // In dev mode, call `npm run start` once // the bundle has been generated !production && serve(), // Watch the `public` directory and refresh the // browser on changes when not in production !production && livereload('public'), // If we're building for production (npm run build // instead of npm run dev), minify production && terser() ], watch: { clearScreen: false } };
postcss.config.js
module.exports = () => ({ plugins: [require("tailwindcss")], })
解决方案
1. 绑定radio状态到Store(核心修复)
问题根源是radio的checked属性未与Svelte Store同步,导致DOM中的单选框状态与实际选择不一致,进而使Tailwind的peer-checked选择器无法正确触发。修改代码,使用bind:checked将单选框状态与Store值关联:
<div class="flex justify-center mt-3 mb-2"> <div class="inline-flex outline outline-neutral-100 rounded-md"> <div> <input type="radio" name="radio" id="internato" class="sr-only peer" bind:checked={$spotTypeBeforeAPICall === spotTypes.INTERNATO} on:click={() => { $spotTypeBeforeAPICall = spotTypes.INTERNATO; }} /> <label for="internato" class="cursor-pointer inline-flex items-center py-2 px-3 text-base sm:text-lg peer-checked:bg-neutral-100 peer-checked:text-cyan-900 peer-checked:font-bold hover:font-bold" > IFE </label> </div> <div> <input type="radio" name="radio" id="iac" class="sr-only peer" bind:checked={$spotTypeBeforeAPICall === spotTypes.IAC} on:click={() => { $spotTypeBeforeAPICall = spotTypes.IAC; }} /> <label for="iac" class="cursor-pointer inline-flex items-center py-2 px-3 text-base sm:text-lg peer-checked:bg-neutral-100 peer-checked:text-cyan-900 peer-checked:font-bold hover:font-bold" > IAC </label> </div> </div> </div>
2. 优化DOM结构(可选)
将单选框直接嵌套在label内,减少DOM层级,避免浏览器对兄弟选择器的解析差异:
<div class="flex justify-center mt-3 mb-2"> <div class="inline-flex outline outline-neutral-100 rounded-md"> <label class="cursor-pointer inline-flex items-center py-2 px-3 text-base sm:text-lg"> <input type="radio" name="radio" class="sr-only peer" bind:checked={$spotTypeBeforeAPICall === spotTypes.INTERNATO} on:click={() => $spotTypeBeforeAPICall = spotTypes.INTERNATO} /> <span class="peer-checked:bg-neutral-100 peer-checked:text-cyan-900 peer-checked:font-bold hover:font-bold">IFE</span> </label> <label class="cursor-pointer inline-flex items-center py-2 px-3 text-base sm:text-lg"> <input type="radio" name="radio" class="sr-only peer" bind:checked={$spotTypeBeforeAPICall === spotTypes.IAC} on:click={() => $spotTypeBeforeAPICall = spotTypes.IAC} /> <span class="peer-checked:bg-neutral-100 peer-checked:text-cyan-900 peer-checked:font-bold hover:font-bold">IAC</span> </label> </div> </div>
3. 完善PostCSS配置确保兼容性
添加autoprefixer插件,确保生成的CSS兼容所有现代浏览器:
module.exports = () => ({ plugins: [ require("tailwindcss"), require("autoprefixer") ], })
同时确保安装了最新版本的Tailwind CSS和PostCSS依赖:
npm install tailwindcss@latest postcss@latest autoprefixer@latest
验证步骤
- 重启开发服务器
- 清除浏览器缓存后重新测试
- 确认Chrome和Safari中选中选项的样式正常生效
内容的提问来源于stack exchange,提问作者Gustavo Morais
相关产品推荐
相关产品推荐

