twbs/bootstrap-icons
Official open-source Bootstrap SVG icon library with 2,000+ icons. Install via npm or Composer and use by embedding SVGs, referencing with , using the sprite, or via CSS. Explore the full icon set and usage docs at icons.getbootstrap.com.
Install via npm (recommended for Laravel projects using Vite/Webpack):
npm install bootstrap-icons
Add to your resources/js/app.js or resources/css/app.scss:
import 'bootstrap-icons/font/bootstrap-icons.css';
Or in app.scss:
@import "bootstrap-icons/font/bootstrap-icons";
CDN Alternative (quickest for testing):
Add to resources/views/layouts/app.blade.php:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
First Use Case:
<!-- Blade template -->
<i class="bi bi-heart-fill text-danger"></i>
Or inline SVG:
<svg class="bi" width="16" height="16" fill="currentColor">
<use xlink:href="#heart-fill"/>
</svg>
node_modules/bootstrap-icons/bootstrap-icons.svgnode_modules/bootstrap-icons/font/fonts/Workflow:
npm install bootstrap-icons --save-dev
// vite.config.js
export default defineConfig({
resolve: {
alias: {
'@icons': path.resolve(__dirname, 'node_modules/bootstrap-icons'),
},
},
});
<button class="btn btn-outline-primary">
<i class="bi bi-cloud-upload"></i> Upload
</button>
Dynamic Icons (Laravel + Blade):
<i class="bi bi-{{ $iconName }}"></i>
Pattern: Use the sprite for performance (single HTTP request).
app.blade.php):
<svg style="display: none;">
<use xlink:href="#heart-fill"/>
</svg>
<svg class="bi" width="1em" height="1em" viewBox="0 0 16 16">
<use xlink:href="#heart-fill"/>
</svg>
<svg class="bi" width="1em" height="1em" viewBox="0 0 16 16">
<use xlink:href="{{ asset('node_modules/bootstrap-icons/bootstrap-icons.svg#'.$dynamicIcon) }}"/>
</svg>
Use Case: Icons with dynamic colors/sizes.
@php
$color = auth()->check() ? 'success' : 'secondary';
$size = request('size') ?: '16';
@endphp
<svg class="bi text-{{ $color }}" width="{{ $size }}" height="{{ $size }}" fill="currentColor">
<use xlink:href="#{{ $icon }}"/>
</svg>
For Themed Icons:
// resources/scss/custom.scss
@import "bootstrap-icons/font/bootstrap-icons";
.icon-theme {
.bi {
color: $primary;
}
.bi-heart {
color: $danger;
}
}
Decorative Icons:
<i class="bi bi-search" aria-hidden="true"></i>
Interactive Icons:
<button aria-label="Notifications">
<i class="bi bi-bell-fill" role="img"></i>
</button>
<use> Issues<use> with external sprites (e.g., CDN).<!-- Local sprite (recommended) -->
<svg class="bi" width="1em" height="1em">
<use xlink:href="{{ asset('node_modules/bootstrap-icons/bootstrap-icons.svg#icon-name') }}"/>
</svg>
font-face fails if paths aren’t absolute.// vite.config.js
export default defineConfig({
assetsInclude: ['**/*.svg'],
resolve: {
alias: {
'@icons': path.resolve(__dirname, 'node_modules/bootstrap-icons'),
},
},
});
<link rel="preload" href="{{ asset('node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff2') }}" as="font" type="font/woff2" crossorigin>
// app/Helpers/IconHelper.php
public static function isValidIcon(string $name): bool {
return file_exists(resource_path("node_modules/bootstrap-icons/icons/{$name}.svg"));
}
Usage:
@if(IconHelper::isValidIcon($iconName))
<i class="bi bi-{{ $iconName }}"></i>
@endif
svgo to optimize SVGs before committing:
npx svgo --multipass --config=node_modules/bootstrap-icons/.svgo.config.js icons/*.svg
currentColor + CSS variables:
.dark-mode {
.bi {
color: var(--bs-dark-icon-color);
}
}
node_modules by default.webpack.mix.js:
mix.copy('node_modules/bootstrap-icons', 'public/vendor/bootstrap-icons');
// app/Services/IconService.php
public function getIconList(): array {
return array_map(
fn($file) => pathinfo($file, PATHINFO_FILENAME),
glob(resource_path('node_modules/bootstrap-icons/icons/*.svg'))
);
}
fill="currentColor").resources/svg/custom/ and reference:
<svg class="bi" width="1em" height="1em" viewBox="0 0 16 16">
<use xlink:href="{{ asset('svg/custom/your-icon.svg#icon-viewbox') }}"/>
</svg>
node_modules/bootstrap-icons/icons/.bi-heart vs bi-heart-fill).<use> href for typos (e.g., #heart-fill vs #heartfill).How can I help you explore Laravel packages today?