Skip to content

Instantly share code, notes, and snippets.

@cb109
Last active May 5, 2022 15:40
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save cb109/b074a65f7595cffc21cea59ce8d15f9b to your computer and use it in GitHub Desktop.
Save cb109/b074a65f7595cffc21cea59ce8d15f9b to your computer and use it in GitHub Desktop.
Vue Breakpoints Mixin (also available via npm: https://www.npmjs.com/package/vue-md-breakpoint)
// Now officially integrated into Vuetify:
//
// https://github.com/vuetifyjs/vuetify/blob/master/src/components/VApp/mixins/app-breakpoint.js
// https://github.com/vuetifyjs/vuetify/blob/master/src/components/VApp/mixins/app-breakpoint.spec.js
/**
* A Vue mixin to get the current width/height and the associated breakpoint.
*
* Useful to e.g. adapt the user interface from inside a Vue component
* as opposed to using CSS classes. The breakpoint pixel values and
* range names are taken from Vuetify (https://github.com/vuetifyjs).
*
* Use within a component:
*
* import breakpoint from './breakpoint.js';
*
* export default {
* name: 'my-component',
* mixins: [breakpoint],
* ...
*
* Then inside a template:
*
* <div v-if="$breakpoint.smAndDown">...</div>
*/
var breakpoint = {
data() {
return {
clientWidth: 0,
clientHeight: 0,
};
},
computed: {
$breakpoint() {
let xs = this.clientWidth < 600;
let sm = this.clientWidth < 1024 && !xs;
let md = this.clientWidth < (1440 - 16) && !(sm || xs);
let lg = this.clientWidth < (1920 - 16) && !(md || sm || xs);
let xl = this.clientWidth >= (1920 - 16) && !(lg || md || sm || xs);
let xsOnly = xs;
let smOnly = sm;
let smAndDown = (xs || sm) && !(md || lg || xl);
let smAndUp = !xs && (sm || md || lg || xl);
let mdOnly = md;
let mdAndDown = (xs || sm || md) && !(lg || xl);
let mdAndUp = !(xs || sm) && (md || lg || xl);
let lgOnly = lg;
let lgAndDown = (xs || sm || md || lg) && !xl;
let lgAndUp = !(xs || sm || md) && (lg || xl);
let xlOnly = xl;
let name;
switch(true) {
case (xs):
name = 'xs';
break;
case (sm):
name = 'sm';
break;
case (md):
name = 'md';
break;
case (lg):
name = 'lg';
break;
default:
name = 'xl';
break;
}
let result = {
// Definite breakpoint.
'xs': xs,
'sm': sm,
'md': md,
'lg': lg,
'xl': xl,
// Useful e.g. to construct CSS class names dynamically.
'name': name,
// Breakpoint ranges.
'xsOnly': xsOnly,
'smOnly': smOnly,
'smAndDown': smAndDown,
'smAndUp': smAndUp,
'mdOnly': mdOnly,
'mdAndDown': mdAndDown,
'mdAndUp': mdAndUp,
'lgOnly': lgOnly,
'lgAndDown': lgAndDown,
'lgAndUp': lgAndUp,
'xlOnly': xlOnly,
// For custom breakpoint logic.
'width': this.clientWidth,
'height': this.clientHeight,
};
return result;
},
},
methods: {
_updateDimensions() {
// Cross-browser support as described in:
// https://stackoverflow.com/questions/1248081
this.clientWidth = Math.max(document.documentElement.clientWidth,
window.innerWidth || 0);
this.clientHeight = Math.max(document.documentElement.clientHeight,
window.innerHeight || 0);
},
},
mounted() {
this.$nextTick(() => {
this._updateDimensions();
window.addEventListener('resize', this._updateDimensions,
{'passive': true});
});
},
destroyed() {
window.removeEventListener('resize', this._updateDimensions);
},
};
export default breakpoint;
@cyrrill
Copy link

cyrrill commented Aug 2, 2017

Nice job @cb109! I've cross-referenced it with an open issue in the Vuetify repo:

vuetifyjs/vuetify#974

@guykatz
Copy link

guykatz commented Aug 4, 2017

looks exactly like what I needed!
is this going to be incorporated to the main vuetify release?

@antoniogiroz
Copy link

Awesome!! Thanks!

@cb109
Copy link
Author

cb109 commented Sep 11, 2017

This has been integrated into Vuetify 0.15 and is available as vm.$vuetify.breakpoint ❤️

@nick-ChenZe
Copy link

Hi, @cb109 great work for this!
Can you help me to understand this expression. 1440 - 16 what does 16 means ? Why should subtract this?
Thanks.

@cb109
Copy link
Author

cb109 commented Jan 17, 2018

@nick-ChenZe Sorry haven't seen your comment until now. I took these expressions from the Vuetify source code, which in turn is based on the material design guidelines (https://material.io/guidelines/layout/responsive-ui.html#responsive-ui-breakpoints). Vuetify by default always shows a scrollbar which is 16px wide, so this is subtracted there. Not sure why it's only done for some of the breakpoints. People in the Vuetify Discord channel will be able to tell you though: https://discordapp.com/channels/340160225338195969/340215499398840331

@nick-ChenZe
Copy link

@cb109 Thank you for your patient reply.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment