or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-postcss-focus-visible

PostCSS plugin that transforms :focus-visible pseudo-class selectors into compatible class-based selectors for cross-browser support

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/postcss-focus-visible@10.0.x

To install, run

npx @tessl/cli install tessl/npm-postcss-focus-visible@10.0.0

0

# PostCSS Focus Visible

1

2

PostCSS Focus Visible is a PostCSS plugin that transforms `:focus-visible` pseudo-class selectors into compatible class-based selectors for cross-browser support. It implements the CSS Selectors Level 4 specification for :focus-visible, providing better accessibility by distinguishing between keyboard and mouse focus states.

3

4

## Package Information

5

6

- **Package Name**: postcss-focus-visible

7

- **Package Type**: npm

8

- **Language**: TypeScript

9

- **Installation**: `npm install postcss-focus-visible --save-dev`

10

11

## Core Imports

12

13

ES Modules (preferred):

14

15

```typescript

16

import postcssFocusVisible from "postcss-focus-visible";

17

```

18

19

For TypeScript with options:

20

21

```typescript

22

import postcssFocusVisible, { pluginOptions } from "postcss-focus-visible";

23

```

24

25

CommonJS:

26

27

```javascript

28

const postcssFocusVisible = require("postcss-focus-visible");

29

```

30

31

## Basic Usage

32

33

The plugin transforms `:focus-visible` selectors into class-based equivalents that work with the focus-visible polyfill:

34

35

```javascript

36

const postcss = require('postcss');

37

const postcssFocusVisible = require('postcss-focus-visible');

38

39

postcss([

40

postcssFocusVisible()

41

]).process(yourCSS);

42

```

43

44

Input CSS:

45

46

```css

47

:focus:not(:focus-visible) {

48

outline: none;

49

}

50

```

51

52

Output CSS (with default options):

53

54

```css

55

:focus:not(.focus-visible).js-focus-visible, .js-focus-visible :focus:not(.focus-visible) {

56

outline: none;

57

}

58

:focus:not(:focus-visible) {

59

outline: none;

60

}

61

```

62

63

## Capabilities

64

65

### Main Plugin Function

66

67

Creates a PostCSS plugin instance with optional configuration.

68

69

```typescript { .api }

70

/**

71

* Creates a PostCSS plugin that transforms :focus-visible pseudo-selectors

72

* @param opts - Optional plugin configuration

73

* @returns PostCSS plugin instance

74

*/

75

function postcssFocusVisible(opts?: pluginOptions): PostCSS.Plugin;

76

```

77

78

The plugin automatically:

79

- Detects `:focus-visible` pseudo-classes in selectors

80

- Replaces them with configurable class selectors (default: `.focus-visible`)

81

- Adds polyfill-ready class prefixes for compatibility (default: `.js-focus-visible`)

82

- Preserves original selectors alongside transformed ones (configurable)

83

84

### Configuration Options

85

86

Plugin behavior can be customized through the options parameter.

87

88

```typescript { .api }

89

interface pluginOptions {

90

/** Preserve the original notation. default: true */

91

preserve?: boolean;

92

/** The replacement class to be used in the polyfill. default: ".focus-visible" */

93

replaceWith?: string;

94

/** Disable the selector prefix that is used to prevent a flash of incorrectly styled content. default: false */

95

disablePolyfillReadyClass?: boolean;

96

}

97

```

98

99

**preserve (boolean, default: true)**

100

- `true`: Keeps both original and transformed selectors in output

101

- `false`: Removes original selectors, leaving only transformed ones

102

103

Example with `preserve: false`:

104

105

```javascript

106

postcssFocusVisible({ preserve: false })

107

```

108

109

Input:

110

```css

111

:focus:not(:focus-visible) {

112

outline: none;

113

}

114

```

115

116

Output:

117

```css

118

:focus:not(.focus-visible).js-focus-visible, .js-focus-visible :focus:not(.focus-visible) {

119

outline: none;

120

}

121

```

122

123

**replaceWith (string, default: ".focus-visible")**

124

125

Defines the replacement selector for `:focus-visible`. Must be compatible with the focus-visible polyfill if used.

126

127

Example with custom replacement:

128

129

```javascript

130

postcssFocusVisible({ replaceWith: '[data-focus-visible-added]' })

131

```

132

133

Input:

134

```css

135

:focus:not(:focus-visible) {

136

outline: none;

137

}

138

```

139

140

Output:

141

```css

142

:focus:not([data-focus-visible-added]).js-focus-visible, .js-focus-visible :focus:not([data-focus-visible-added]) {

143

outline: none;

144

}

145

:focus:not(:focus-visible) {

146

outline: none;

147

}

148

```

149

150

**disablePolyfillReadyClass (boolean, default: false)**

151

152

Controls whether selectors are prefixed with the polyfill-ready class (`.js-focus-visible`). The polyfill-ready class ensures styles only apply when the polyfill is loaded and active.

153

154

Example with disabled polyfill-ready class:

155

156

```javascript

157

postcssFocusVisible({ disablePolyfillReadyClass: true })

158

```

159

160

Input:

161

```css

162

:focus:not(:focus-visible) {

163

outline: none;

164

}

165

```

166

167

Output:

168

```css

169

:focus:not(.focus-visible) {

170

outline: none;

171

}

172

:focus:not(:focus-visible) {

173

outline: none;

174

}

175

```

176

177

### Plugin Properties

178

179

The plugin function includes standard PostCSS plugin properties.

180

181

```typescript { .api }

182

/**

183

* PostCSS plugin flag indicating this is a valid PostCSS plugin

184

*/

185

postcssFocusVisible.postcss: true;

186

```

187

188

## Integration Patterns

189

190

### With PostCSS CLI

191

192

```bash

193

npx postcss src/*.css --use postcss-focus-visible --dir dest

194

```

195

196

### With Webpack and postcss-loader

197

198

```javascript

199

module.exports = {

200

module: {

201

rules: [

202

{

203

test: /\.css$/,

204

use: [

205

'style-loader',

206

'css-loader',

207

{

208

loader: 'postcss-loader',

209

options: {

210

postcssOptions: {

211

plugins: [

212

require('postcss-focus-visible')()

213

]

214

}

215

}

216

}

217

]

218

}

219

]

220

}

221

};

222

```

223

224

### With PostCSS Load Config

225

226

Create a `postcss.config.js` file:

227

228

```javascript

229

module.exports = {

230

plugins: [

231

require('postcss-focus-visible')({

232

preserve: true,

233

replaceWith: '.focus-visible'

234

})

235

]

236

};

237

```

238

239

## Polyfill Integration

240

241

This plugin is designed to work with the [focus-visible polyfill](https://github.com/WICG/focus-visible). The polyfill should be included in your JavaScript bundle:

242

243

```bash

244

npm install focus-visible

245

```

246

247

```javascript

248

import 'focus-visible';

249

```

250

251

The polyfill automatically:

252

- Adds the `.js-focus-visible` class to the document when loaded

253

- Manages the `.focus-visible` class on focused elements based on focus method

254

- Provides consistent behavior across all browsers

255

256

## Error Handling

257

258

The plugin includes built-in error handling for malformed selectors:

259

260

- Invalid CSS selectors are logged as warnings and left unchanged

261

- Malformed `:focus-visible` pseudo-classes are skipped

262

- Processing continues for valid selectors even if some fail to parse

263

264

## Browser Compatibility

265

266

- **Modern browsers**: Native `:focus-visible` support (Chrome 86+, Firefox 85+, Safari 15.4+)

267

- **Legacy browsers**: Requires focus-visible polyfill for full functionality

268

- **Node.js**: Requires Node.js 18+ (as specified in package engines)

269

270

## Dependencies

271

272

- **postcss-selector-parser**: CSS selector parsing and manipulation (runtime dependency)

273

- **postcss**: PostCSS framework (peer dependency ^8.4)