GithubHelp home page GithubHelp logo

alexandrebonaventure / vue-mq Goto Github PK

View Code? Open in Web Editor NEW
535.0 7.0 58.0 1.85 MB

๐Ÿ“ฑ ๐Ÿ’ป Define your breakpoints and build responsive design semantically and declaratively in a mobile-first way with Vue.

Home Page: https://alexandrebonaventure.github.io/vue-mq

License: MIT License

JavaScript 100.00%
vuejs vuejs2 media mediaqueries viewport breakpoints

vue-mq's Introduction

Vue MQ (MediaQuery)

Define your breakpoints and build responsive design semantically and declaratively in a mobile-first way with Vue.

_Use with vue: ^2.x.x _

Demo: here

Table of Contents

Installation

Using NPM

npm install vue-mq

Using Yarn

yarn add vue-mq

Usage

1. Install plugin

Define your custom breakpoints by passing breakpoints option. This let you name the breakpoints as you want Eg: { phone: 500, tablet: 1200, other: Infinity } { small: 500, large: 1200, whatever: Infinity } { xs: 300, s: 500, m: 800, l: 1200, xl: Infinity }

import Vue from 'vue'
import VueMq from 'vue-mq'

Vue.use(VueMq, {
  breakpoints: { // default breakpoints - customize this
    sm: 450,
    md: 1250,
    lg: Infinity,
  }
  defaultBreakpoint: 'sm' // customize this for SSR
})

Use $mq property

After installing the plugin every instance of Vue component is given access to a reactive $mq property. Its value will be a String which is the current breakpoint.

Eg: (with default breakpoints) 'sm' => 0 > screenWidth < 450 'md' => 450 >= screenWidth < 1250 'lg' => screenWidth >= 1250

//Use it in a component
new Vue({
  template: `
    <h1>current: {{$mq}}</h1>
  `,
})

Use $mq property with the mq filter

Using the filter allow to build your responsive design in a declarative way. This can be very useful and elegant to pass down props to layout component. (eg: a grid system)

new Vue({
  template: `
    <grid-component :column="$mq | mq({ sm: 1, md: 2, lg: 3 })">
    </grid-component>
  `,
})

Remember that the filter design embrace mobile-first philosophy so writing $mq | mq({ sm: 1, lg: 3 }) will output 1 for md breakpoint if omited. In short it will always fallback to the smallest breakpoint (aka mobile) if value isn't overriden by a largest breakpoint.

Use $mq with a computed property

$mq property is fully reactive (like a data property) so feel free to use it in a computed.

new Vue({
  computed: {
    displayText() {
      return this.$mq === 'sm' ? 'I am small' : 'I am large'
    }
  },
  template: `
    <h1>{{displayText}}</h1>
  `,
})

MqLayout component

In addition to $mq property this plugin provide a wrapper component to facilitate conditional rendering with media queries.

Usage:

<mq-layout mq="lg">
  <span> Display on lg </span>
</mq-layout>
<mq-layout mq="md+">
  <span> Display on md and larger </span>
</mq-layout>
<mq-layout :mq="['sm', 'lg']">
  <span> Display on sm and lg </span>
</mq-layout>

Props mq => required : String | Array

Important: note that you can append a + modifier at the end of the string to specify that the conditional rendering happens for all greater breakpoints.

SSR Support

v1.0+ now supports SSR. You can customize the defaultBreakpoint which let you set the breakpoint used by the server-side-rendering

Browser Support

This plugin relies on matchMedia API to detect screensize change. So for older browsers and IE, you should polyfill this out: Paul Irish: matchMedia polyfill

Support

Please open an issue for support.

vue-mq's People

Contributors

akiyamka avatar alexandrebonaventure avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue-mq's Issues

Custom breakpoints

I try and define my custom breakpoints to match my sass (in my main app.js)

import VueMq from 'vue-mq';
Vue.use(VueMq, {
  breakpoints: {
    xsmall: 500,
    small: 768,
    medium: 1024,
    large: 1360,
    xlarge: 1800
  }
});

When I {{ $mq }} in my component I get the defaults, 'tablet', 'laptop' etc.

Media query boundaries

I have the following custom breakpoints

Vue.use(VueMq, {
  breakpoints: {
    xsmall: 500,
    small: 768,
    medium: 1024,
    large: 1360,
    xlarge: 1800
  }
});

I want to do the following

 <span v-if="$mq==='small'>
       some text
            </span>
    <span v-else>
           diffrent text
 </span>

The text does change but as soon as I resize to the 'medium' breakpoint it reverts.

This would work but is a bit messy, is there not a way to check for small or above?

 <span v-if="$mq==='small' || $mq=='medium || $mq == 'large' || $mq == 'xlarge">
       some text
            </span>
    <span v-else>
           diffrent text
 </span>

How to install plugin in Vue3?

Installing plugins has changed in v3.
Can vue-mq be used with vue v3?

const chat = createApp(App);
chat.use(store);
chat.use(router);
chat.use(VueMq, {
  breakpoints: {
    mobile: 375,
    tablet: 680,
    laptop: 1280,
    desktop: Infinity,
  },
  defaultBreakpoint: "mobile",
});

chat.mount("#app");

Results in vue-mq.es.js?660e:122 Uncaught TypeError: Vue is not a constructor at Object.install (vue-mq.es.js?660e:122) at Object.use (runtime-core.esm-bundler.js?5c40:3360)

Suggestion: Not wrap MqLayout content in a <div>

Right now when you use

<mq-layout mq="md">
  <div class="medium-layout">Medium Layout</div>
</mq-layout>

It will compile into

<div>
  <div class="medium-layout">Medium Layout</div>
</div>

I think it would be much easier for layout purposes that it would not encapsulate around an empty <div>

Create height based media query

Hello there,

I would like to know how to create a media query for height? For example, I would like to create a media query like this

@media screen and (max-height: 800px){}

[Feature request] $mq should work as a function

Right now $mq is just a string - that is limiting its behavior significantly. I suggest to turn it into a function that could accept a string. That will enable true mobile-first experience. If an argument of specified breakpoint is passed - it should return true if it's currently within that breakpoint.
If a minus is added to the string - it will also include every breakpoint below the specified one.
If a plus is added to the string - it will also include every breakpoint above the specified one. Something like:

this.$mq('md') // will return true if screen width is == 'md'
this.$mq('md-') // will return true if screen width is <= 'md'
this.$mq('md+') // will return true if screen width is >= 'md'
this.$mq() // will return current breakpoint similar to how it's working now

+ modifer not working appending to string

Hello,

I'm trying to get the + modifier to work in a conditional string, but it does not seem to work.

Important: note that you can append a + modifier at the end of the string to specify that the conditional rendering happens for all greater breakpoints.

Vue.use(VueMq, {
  breakpoints: {
    mobile: 450,
    tablet: 900,
    laptop: 1250,
    desktop: Infinity
  }
})

<div v-if="$mq == 'tablet+'">tablet and higher</div>

It works just fine without the +, but I'm trying to trigger my tablet+ sizing. Do I need to use the MqLayout component for this to work?

Thanks!

Is bili a needed dependency?

It's huge, is it needed for other than packaging? I don't want to pull down so many babel & rollup dependencies. Was it meant to be put as dev-dependency?

Ability to set `defaultBreakpoint` dynamically in nuxt module

Feature Suggestion
Add the possibility to set the defaultBreakpoint dynamically when using nuxt module.

Why?
To prevent misbehavior of components when reloading a page in a screen size that is not the default. Components that depends on $mq are wrongly shown or hidden while vue-mq is not fully loaded in the frontend application, causing a blink of very misplaced ui components for a few seconds.

Suggested solution
With SSR it's possible to have a header telling the screen size of origin request. We could have something like:

/**
* nuxt-mq
*/
mq: {
  defaultBreakpoint: (req) => {
    if (req.headers['CloudFront-Is-Mobile-Viewer']) {
      return 'modernPhone';
    }
    if (req.headers['CloudFront-Is-Tablet-Viewer']) {
      return 'tablet';
    }
    return 'desktop';
  },
  breakpoints: {
    oldPhone: 375, // 0 ~ 374
    modernPhone: 800, // 375 ~ 799
    tablet: 1000, // 800 ~ 999
    notebook: 1200, // 1100 ~ 1199
    desktop: Infinity, // 1300+
  },
},

Expose currentBreakpoint via global property?

Started using this today and it's fantastic ๐Ÿ‘ thank you ๐Ÿ™. The only problem I ran into was not being able to access the current breakpoint outside a component, vuex in our case. What are you thoughts on exposing currentBreakpoint via a global property?

MqLayout component minus modifier

Hay! Thanks for this plugin!
I'm looking for a - modifier. Is this in any way possible with the mq-layout component?

<mq-layout mq="md-">
   ....
</mq-layout>

Cheers

Add a less-than modifier like the + modifier

The plus modifier is really useful, and we're using :mq="['xs', 'sm']" in a lot of places for Bootstrap. It would be really helpful to have a - operator, so we could do mq="sm-" instead.

Can't resolve 'vue-mq' because dist folder not in the package

I have a weird issue when I install the package following the documentation:
npm install vue-mq

I can't resolve the package because the dist folder is not present and the main attribute is set as "dist/vue-mq.js".

It seems to be the case only for the last version.

Vue-mq crash whole app on ipad iOS 9.3.5

[Error] TypeError: Object.values is not a function. (In 'Object.values(t)', 'Object.values' is undefined)
(anonymous function) (vendor.bb871968581eb32b7779.js:1:262533)
install (vendor.bb871968581eb32b7779.js:1:262685)
use (vendor.bb871968581eb32b7779.js:1:173054)
NHnr (app.9b13ddd7c0531c02fe13.js:1:111824)
o (manifest.b2235280efe91100e06a.js:1:415)
webpackJsonp (manifest.b2235280efe91100e06a.js:1:286)
Global Code (app.9b13ddd7c0531c02fe13.js:1)

Hello seems vue-mq is crashing app content injection

Thanks a lot for this Wonderfull plugin

Typescript support

Hi,

First of all, thank you for your excellent work.
Could you provide typings file in order to be able to work with typescript ?

VueMq($mq) computed value is not reactive when using Nuxt.

When I resize the browser window, the value for $mq remains the same. But in the demo, it is reactive.
Here's my code below:

plugins/vue-mq.js
`import Vue from 'vue'
import VueMq from 'vue-mq'

// Vue MQ
Vue.use(VueMq, {
breakpoints: {
// default breakpoints - customize this
sm: 640,
md: 768,
lg: 1024,
xl: 1280,
xxl: 1440,
},
defaultBreakpoint: 'sm', // customize this for SSR
})
`

nuxt.config.js
plugins: [{ src: '~plugins/vue-mq.js', ssr: false }],

The value of $mq is not correct on mouted

// main.js
Vue.use(VueMq, { 
  breakpoints: {
    xs: 468,
    sm: 768,
    md: 1080,
    lg: Infinity
  }
})

// App.js
{
  mounted () {
    console.log(this.$mq) // sm, but the viewport size was matched `lg`
  }
}

SSR how to set defaultBreakpoint value according to serverMiddleware function?

Hi All

I can't find a solution for this for a long time.

I have serverMiddleware function:

device-detect.js

import parser from 'ua-parser-js';

export default (req, res, next) => {
  const ua = parser(req.headers['user-agent']);
  console.log(ua.device.type);  // returns: console, mobile, tablet, smarttv, wearable, embedded
  req.device = ua.device.type;  // I tried by req
  next();
}

nuxt.config.js

serverMiddleware: [
    '~/server_middlewares/device-detect.js'
  ]

And now I would like to set the defaultBreakpoint value in accordance with what this function decodes in plugin
media-query.js

import Vue from 'vue';
import VueMq from 'vue-mq';

Vue.use(VueMq, {
  breakpoints: { // default breakpoints - customize this
    phone: 500,
    tablet: 700,
    desktop: Infinity
  },
  defaultBreakpoint:  // < How to set it according to the function device-detect.js  
})

Thanks to this, we will avoid generating SSR incompatible with the device.

Do you have any ideas how to do it?

Thx

Can't update breakpoints

I have an application where the user can specify breakpoints to render different data. I cannot change the breakpoint at runtime however. Calling Vue.use(VueMq, { ... }) when it's already set doesn't do anything.

Something along the lines of this would be great:

Vue.use(VueMq, {
  breakpoints: { // default breakpoints - customize this
    sm: 450,
    md: 1250,
    lg: Infinity,
  }
  defaultBreakpoint: 'sm' // customize this for SSR
})

// in component
this.$mq.update('sm', 550)

Crush in IE11

Object.values not implemented in IE, and it is difficult to polyfill. Since Vue supprots IE8+, it would be better to use something from es5.

[Enhancement] Sanitize pixel input

I'm currently using this VERY HANDY package and am VERY happy it exists. However, when I attempted to use a "non-perfect" Object I ran into some rather annoying issues.

I am suggesting to accept a string in the pixel value and have it "clean" it and use the result. There's probably a better way to do it, but I ended up doing this to "fix" my object to meet the standards.

The reason I want this is because I'm taking the breakpoints from an external json object which begins with a "sm": "560px" lookin thing (tailwind config).

// Initial object looks like this:
// let fixedScreens = {"sm":"640px","md":"768px","lg":"1024px","xl":"1280px"}

for (const property in fixedScreens) {
    fixedScreens[property] = fixedScreens[property].replace(/px/g, '')
    if (RegExp('[-+]?[0-9]*\.?[0-9]+', 'g').test(fixedScreens[property])) {
        fixedScreens[property] = Number(fixedScreens[property])
    }
}

// fixedScreens now looks like 
// {sm: 640, md: 768, lg: 1024, xl: 1280}

const options = {
    breakpoints: fixedScreens,
    defaultBreakpoint: Object.keys(fixedScreens)[0],
}

I thought I would DEFINITELY need to remove the "px" characters, but I was baffled that it wouldn't take a string value and convert it into a number automagically. I would have sent a PR but I honestly don't know where to change it !

Not working on Boolean value

Use $mq | mq({ mobile: false, desktop: true }) is working.

But $mq | mq({ mobile: true, desktop: false }) will always be true.

SSR not working with `mq-layout`

Good day,
I'm using ssr for my project, and if im using
<mq-layout mq="mobile">
it renders <mq-layout> instead of a div and ignores the breakpoint.

When im using <div v-if="$mq === 'mobile'> it works as intented.
This only happens while using SSR.

MQ not available on initial load

[Vue warn]: Property or method "$mq" is not defined on the instance but referenced during render. 

Make sure that this property is reactive, either in the data option, or for class-based components, 
by initializing the property. 
See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

found in

---> <App> at src/App.vue
       <Root>

I get this error message everytime I initial load my page. It doesnt work in developing mode with HMR active. After changing and saving the file without reloading the page but using HMR to update it the mediaquery seems to work.
Same problem after building the project and uploading it to a webserver.

Do i miss something or is there a problem while using
node v8.12.0
vue v3.0.4
in my project?

My template:

<template>
    <div id="app">
        <div id="nav">
            <div>currentBreakpoint: {{$mq}}</div>
        </div>
    </div>
</template>

How to add mutliple breakpoints in one check

Is this possible in a terse way? E.g. I'm a beginner mind you.

v-if="$mq === 'large' || 'medium'"

I'm currently using this which feels like a mouthfull.

v-if="$mq === 'smaller' || $mq === 'small'"

Doesn't work on small breakpoint

Hello
I have following config:
Vue.use(VueMq, { breakpoints: { xs: 400, lg: 1000, xl: 1400 } })

in Template
This: {{$mq}}

It never shows the xs breakpoint. (lg and xl work)

I tested with chrome devtools

How i can use with javascript like lit element

Hi Team,

It is an excellent plugin that works fine with vue js but if I need to work with javascript Lit elements.
Do you have any documentation on how it will work with Lit element?

A suggestion

Instead of using a string, you could use an object with all the breakpoints assigned to a boolean

For example:

$mq: { mobile: false, tablet: false, desktop: true }

This way it would be easier to make comparisons in the templates.

v-if="$mq.mobile"

Website shows a non working example

On the project's website the following line:
<mq-layout :mq="['sm', 'lg']">
is shown without a colon next to "mq". This does not match the GitHub documentation and does not work.

Suggestion: Add CSS Media query to mq-layout component for SSR

For SSR with popular frameworks like for example Nuxt, since window is not available on the server, vue-mq implemented a defaultBreakpoint.

This solves everything with the caveat that if you open the browser to a size different from the defaultBreakpoint, there will still be some flickering happening for a brief second, before window is defined and accordingly hides the content inside mq-layout.

I experimented with solving this issue, and from what I can see this could easily be solved by adding an CSS media query to the mq-layout component that is identical to the props given to mq-layout.

So if you have a layout that is <mq-layout mq="md+"></mq-layout> where

  breakpoints: { // default breakpoints - customize this
    sm: 850,
    md: 1450,
    lg: Infinity,
  },
  defaultBreakpoint: 'lg' // customize this for SSR
})

If we attach a CSS media query to it like

  @media (max-width: 850px) {
    display: none;
  }

The flickering is solved by this, as once the CSS is loaded the content will be hidden from DOM by CSS, and once the component is mounted, vue-mq will kick in and remove it from the DOM.

support for @media print

Thank you for the library, it is working really well.
I was wondering if it is possible to specify what happens when my page is printed.
I have not fully thought through what the best UI would be.

SSR Support

Can't use the plugin in an SSR environment since the 'window' is undefined on the server. Any ideas on how to properly implement this?

Maybe the $isServer property can help here

Update README

Change

<mq-layout mq="['sm', 'lg']">

to

<mq-layout :mq="['sm', 'lg']">

Uncaught SyntaxError: missing } after property list

I apologize I'm new to Vue.js so most likelty I'm doing a mistake.
Took the code from the readme and changed custom values for , but it trows this error.
Current code, at which the error points

Vue.use(VueMq, {
  breakpoints: { // default breakpoints - customize this
    md: 767,
    lg: 1200,
    xl: Infinity,
  }
  defaultBreakpoint: 'md' // customize this for SSR
})


new Vue({
            el: '#sliderportafolio',
             data: {
              slides: 5
            },
            components: {
              'carousel-3d': window['carousel-3d'].Carousel3d,
              'slide': window['carousel-3d'].Slide
            },
            methods: {
             testClick: function (){
             //
             }
           }
          });

$mq props query

I am trying to use prop $mq | mq for grid system. How do use it for a column for different media queries

Creating isMobile / isTablet, etc

How can I extend the global $mq object with reactive isMobile / isTablet / isWide, etc properties?

I want to be able to use it similar to $device.isMobile from Nuxt

<div v-if="$mq.isMobile"> ...

and not the long version like

<div v-if="$mq === mobile"> ...

Any idea on how could I extend it to be working like this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.