How Vue Color Avatar Implements Mobile-Responsive Design: Breakpoints, Media Queries, and Runtime Toggles
Vue Color Avatar achieves mobile-responsive design through SCSS breakpoint variables at 480px, 768px, and 976px, combined with CSS media queries that hide non-essential elements, reclaim sidebar space, and scale the avatar, while JavaScript automatically collapses the sidebar via the useSider hook when viewports drop below 976px.
The vue-color-avatar project demonstrates a sophisticated approach to mobile-responsive design by coordinating CSS media queries with Vue.js reactive state management. By defining consistent breakpoints in SCSS variables and mirroring them in JavaScript constants, the application ensures that layout changes remain synchronized between visual styles and component behavior. This article examines the specific implementation details found in the repository's source code, from breakpoint definitions in src/styles/var.scss to the runtime collapse logic in src/hooks/useSider.ts.
Breakpoint Architecture and SCSS Variables
The foundation of the mobile-responsive design system resides in centralized SCSS variables that establish consistent width thresholds across the application.
In src/styles/var.scss, three primary breakpoints define the responsive behavior:
/* src/styles/var.scss */
$screen-sm: 480px;
$screen-md: 768px;
$screen-lg: 976px;
These values are referenced throughout the stylesheet and JavaScript to decide when to switch layouts. The $screen-sm (480px) threshold targets smartphones, $screen-md (768px) handles tablets, and $screen-lg (976px) determines when the sidebar should collapse or expand.
CSS Media Queries for Layout Adaptation
The application employs targeted media queries to modify layout properties at specific breakpoints, ensuring content remains accessible across device sizes.
Hiding Non-Essential Header Elements
When viewport width drops to 480px or below, the application removes decorative text to prioritize functional controls. In src/layouts/Header.vue, the site title is hidden using a media query:
<!-- src/layouts/Header.vue -->
<style scoped lang="scss">
@use 'src/styles/var';
.site-title {
/* … */
@media screen and (max-width: var.$screen-sm) {
display: none; /* hides title on ≤ 480 px */
}
}
</style>
Container Padding and Sidebar Reclamation
The main container normally reserves space for the sidebar using right padding. On screens 976px or narrower, this padding is cleared to allow the main content to occupy the full width. This logic appears in src/layouts/Container.vue:
<!-- src/layouts/Container.vue -->
<style scoped lang="scss">
@use 'src/styles/var';
.container {
padding-right: var.$layout-sider-width;
@media screen and (max-width: var.$screen-lg) {
padding-right: 0; /* full-width on ≤ 976 px */
}
@media (prefers-reduced-motion: no-preference) {
transition: padding-right 0.2s;
}
}
</style>
Avatar Scaling and Action Button Visibility
To prevent the avatar generator from overflowing on narrow screens, src/App.vue applies a transform scale reduction at the 480px breakpoint. Additionally, the "Download Multiple" button is hidden on small devices to simplify the interface:
<!-- src/App.vue -->
<style scoped lang="scss">
@use 'src/styles/var';
.avatar-wrapper {
@media screen and (max-width: var.$screen-sm) {
transform: scale(0.85); /* shrink avatar on ≤ 480 px */
}
}
/* Additional styles hide the "Download Multiple" button
via display: none within the same media query */
</style>
JavaScript-Driven Sidebar Collapse
While CSS handles visual adaptations, the sidebar's collapsed state requires JavaScript coordination to sync the Vuex store with viewport changes. The application uses a custom hook and a throttled resize listener to manage this behavior.
In src/hooks/useSider.ts, the hook provides methods to control the sidebar state:
// src/hooks/useSider.ts
export function useSider() {
const store = useStore()
const isCollapsed = computed(() => store.isSiderCollapsed)
const openSider = () => store[SET_SIDER_STATUS](false)
const closeSider = () => store[SET_SIDER_STATUS](true)
return { isCollapsed, openSider, closeSider }
}
The src/layouts/Container.vue component implements the resize handler that uses these methods. It checks against the SCREEN.lg constant (976px) defined in src/utils/constant.ts:
// src/layouts/Container.vue (script part)
import { SCREEN } from '@/utils/constant'
import { useSider } from '@/hooks'
const { isCollapsed, openSider, closeSider } = useSider()
function handleWindowResize() {
if (window.innerWidth <= SCREEN.lg) {
closeSider()
} else {
openSider()
}
}
This JavaScript approach ensures that the sidebar state remains consistent with the CSS media query breakpoints, preventing layout shifts when users resize their browsers or rotate mobile devices.
Accessibility and Reduced Motion Support
The mobile-responsive design respects user accessibility preferences through the prefers-reduced-motion media query. Transitions for sidebar sliding and container padding adjustments are only applied when users have not requested reduced motion.
In src/layouts/Sider.vue and src/layouts/Container.vue, transitions are wrapped in conditional media queries:
@media (prefers-reduced-motion: no-preference) {
transition: padding-right 0.2s;
}
This ensures that users with vestibular disorders or motion sensitivity experience immediate state changes without animation, while other users enjoy smooth transitions between responsive states.
Summary
- Centralized breakpoints in
src/styles/var.scssdefine consistent thresholds at 480px, 768px, and 976px for responsive behavior. - CSS media queries hide non-essential elements like the header title and "Download Multiple" button on small screens, while reclaiming sidebar space by removing container padding at 976px and below.
- JavaScript coordination through
src/hooks/useSider.tsandsrc/layouts/Container.vueautomatically collapses the sidebar when viewport width drops below 976px, syncing Vuex state with CSS layout changes. - Visual scaling via
transform: scale(0.85)ensures the avatar remains proportional on screens 480px and narrower without overflowing the viewport. - Accessibility compliance through
prefers-reduced-motionmedia queries respects user preferences by disabling transitions for those sensitive to motion.
Frequently Asked Questions
What breakpoints does Vue Color Avatar use for mobile-responsive design?
The application defines three primary breakpoints in src/styles/var.scss: $screen-sm at 480px for smartphones, $screen-md at 768px for tablets, and $screen-lg at 976px for the sidebar collapse threshold. These values are referenced in both SCSS media queries and JavaScript constants to ensure consistent responsive behavior across the application.
How does the sidebar automatically collapse on mobile devices?
The sidebar uses a combination of JavaScript and Vuex state management through the useSider hook in src/hooks/useSider.ts. The src/layouts/Container.vue component listens for window resize events and calls handleWindowResize(), which checks if window.innerWidth <= SCREEN.lg (976px). When true, it dispatches a store mutation to collapse the sidebar, ensuring the main content area receives full width on tablets and phones.
Why does the avatar scale down on smaller screens?
To prevent the avatar generator interface from overflowing narrow viewports, src/App.vue applies a CSS transform that scales the avatar wrapper to 85% of its original size on screens 480px and below. This transform: scale(0.85) rule maintains the avatar's visual proportions while ensuring it fits comfortably within the constrained horizontal space of mobile devices.
Does Vue Color Avatar support accessibility preferences for motion?
Yes, the application respects the prefers-reduced-motion media query in components like src/layouts/Container.vue and src/layouts/Sider.vue. Transitions for sidebar sliding and padding adjustments are wrapped in @media (prefers-reduced-motion: no-preference) blocks, ensuring that users who experience discomfort from animation see immediate state changes without motion effects.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →