Identifying touchscreen capability through media queries

Is there a secure method, utilizing media queries, to trigger an action when not using a touchscreen device? If not, would you recommend opting for a JavaScript solution like !window.Touch or Modernizr?

Answer №1

In the realm of CSS4 media queries, there exists a property dedicated to exploring the characteristics of pointing devices, as outlined in the CSS4 media query draft.

The ‘pointer’ media feature allows us to delve into the presence and accuracy of different pointing devices, such as mice. It is advised that if a device has multiple input methods, the user agent should convey information about the least precise pointing device of the primary input mechanisms. The values for this media query include:

‘none’
- Indicates that the device lacks a pointing mechanism.

‘coarse’
- Points to a pointing device with limited accuracy in the device's arsenal of input mechanisms.

‘fine’
- Refers to a highly accurate pointing device available within the device's input mechanisms.

Implementing this feature can be done in the following manner:

/* Adjust size of radio buttons and check boxes based on the precision of the pointing device */
@media (pointer:coarse) {
    input[type="checkbox"], input[type="radio"] {
        min-width:30px;
        min-height:40px;
        background:transparent;
    }
}

A related issue in the Chromium project can be explored through this ticket I came across.

To test browser compatibility, one can visit Quirksmode. My findings from January 22, 2013, are as follows:

  • Chrome/Windows: Compatible
  • Chrome/iOS: Not compatible
  • Safari/iOS6: Not compatible

Answer №2

In the current era, CSS Media queries play a crucial role in defining styles tailored for devices with specific interactive capabilities, and it enjoys broad support as well.

The hover feature, for instance, enables testing whether the user's primary input method supports hovering over elements, a functionality that may not be present on touch-enabled devices without emulation.

@media (hover: none) {
  a {
    background: yellow;
  }
}

Other interactive tests include pointer, any-pointer, hover, and any-hover.

Earlier Response

My recommendation would be to utilize modernizr and leverage its media query capabilities.

if (Modernizr.touch){
   // bind to touchstart, touchmove, etc. and monitor `event.streamId`
} else {
   // bind to regular click, mousemove, etc.
}

Alternatively, within CSS, pseudo-classes can also be employed, such as the one available in Firefox. For example, you can use :-moz-system-metric(touch-enabled). Nevertheless, these functionalities may not be universally supported across all browsers.

For Apple gadgets, a straightforward check can be done:

if (TouchEvent) {
   //...
}

Especially tailored for iPad:

if (Touch) {
    // ...
}

It should be noted that these methods do not function properly on Android devices.

Modernizr equips developers with feature detection capabilities, offering an approach based on detecting features rather than relying solely on browsers.

Designing Touch-Responsive Elements

Modernizer incorporates classes into the HTML tag to facilitate this exact purpose. As an example, it adds the classes touch and no-touch, permitting designers to style touch-specific elements by utilizing selectors prefixed with .touch. For instance, .touch .your-container. Credits: Ben Swinburne

Answer №3

In the midst of 2013, the availability of CSS solutions seems to be limited. However...

  1. Nicholas Zakas points out that Modernizr adds a no-touch CSS class if the browser does not support touch.

  2. Alternatively, you could detect it in JavaScript using a simple snippet like this, which enables you to create your own Modernizr-like solution:

    <script>
        document.documentElement.className += 
        (("ontouchstart" in document.documentElement) ? ' touch' : ' no-touch');
    </script>
    

    Then, you can structure your CSS as follows:

    .no-touch .myClass {
        ...
    }
    .touch .myClass {
        ...
    }
    

Answer №4

If you are looking to target a specific media query, you can use the following code snippet:

@media (hover: none) { … }

With good support across browsers like Safari and Chrome on mobile devices, it could be a reliable option until wider adoption is achieved.

Answer №5

Standard media types do not include touch capability detection, making it impossible to consistently achieve this through CSS or media queries:

http://www.w3.org/TR/css3-mediaqueries/

Therefore, the use of JavaScript is necessary for detecting touch capabilities without relying on Modernizr:

<script type="text/javascript">
    var is_touch_device = 'ontouchstart' in document.documentElement;
    if(is_touch_device) alert("Touch support detected!");
</script>

Answer №6

Even in 2017, the CSS media query mentioned in the second answer still doesn't function on Firefox. I managed to find a solution for this issue by using the -moz-touch-enabled property.


Therefore, here is a cross-browser compatible media query:

@media (-moz-touch-enabled: 1), (pointer:coarse) {
    .something {
        it's now working;
    }
}

Answer №7

Feel free to give this a try. If it doesn't work, just reach out.

@media (hover: none) and (pointer: coarse) {
    /* Specific styles for touch screen devices should be placed here */
}

hover:none is considered true when hover functionality is not available

pointer:coarse is considered true when the input accuracy is limited.

If your goal is only to manage hover effects, there is no need to involve pointer.

Edit: Hover on-demand feature has been discontinued.

Answer №8

Until the day when CSS4 is universally supported by all browsers, this solution will suffice. In the meantime, it works well for current browser compatibility.

browser-util.js

export const isMobile = {
  android: () => navigator.userAgent.match(/Android/i),
  blackberry: () => navigator.userAgent.match(/BlackBerry/i),
  ios: () => navigator.userAgent.match(/iPhone|iPad|iPod/i),
  opera: () => navigator.userAgent.match(/Opera Mini/i),
  windows: () => navigator.userAgent.match(/IEMobile/i),
  any: () => (isMobile.android() || isMobile.blackberry() || 
  isMobile.ios() || isMobile.opera() || isMobile.windows())
};

onload:

old way:

isMobile.any() ? document.getElementsByTagName("body")[0].className += 'is-touch' : null;

newer way:

isMobile.any() ? document.body.classList.add('is-touch') : null;

The code above will apply the "is-touch" class to the body element if the device has a touch screen. This allows you to handle hover effects in your web application using

body:not(.is-touch) the_rest_of_my_css:hover
.

For example:

button:hover

becomes:

body:not(.is-touch) button:hover

This method circumvents the need for Modernizr, which can be bulky. If your goal is simply to detect touch screens and minimize the final compiled source size, this approach is ideal.

Answer №9

In my opinion, the most effective approach for styling touch-screen devices using CSS in 2022 is to utilize (pointer:coarse) rather than relying on (hover:none), or a combination of both. It has been observed that (hover:none) can be unreliable as some devices simulate hover behavior through long presses (touch), thus rendering the media query ineffective.

A suggested alternative could be implementing Modernizr or a combination of Modernizr and CSS to address this issue. Utilizing a setup like:

.modernizr-touch-class .my-class { // properties }
@media (pointer:coarse) { .my-class { // same properties } }

However, it is important to note that even with these solutions, reliability may not be guaranteed. Incorporating Modernizr's "Touch Events" test could provide additional insights into potential problems and solutions related to touch-screen compatibility.

Ultimately, it is crucial to acknowledge that (hover:none) may not be a dependable option in 2022. :D

Answer №10

Perfectly functioning on browsers built on Mozilla and Webkit:

/* display only on devices with mouse input */
@media (hover: hover), (-moz-touch-enabled: 0), (pointer:fine) {
    ...
}

/* display only on touch-based devices */
@media (hover: none), (hover: on-demand), (-moz-touch-enabled: 1), (pointer:coarse) {
    ...
}

Answer №11

How to dynamically add a touchscreen class to the body element using JavaScript or jQuery

// Applying mobile-specific CSS
    var isMobile = ('ontouchstart' in document.documentElement && navigator.userAgent.match(/Mobi/));
    if(isMobile){
        jQuery("body").addClass("touchscreen");
    }

Answer №12

This problem was successfully fixed by implementing the following solution:

@media (hover:none), (hover:on-demand) { 
Your specific class or ID{
assigned attributes
}    
}

Answer №13

As of May 5th, 2022:

var isTouch = "maxTouchPoints" in window.navigator && window.navigator.maxTouchPoints > 1;
var isTouchTwo = "ontouchstart" in window;
var isTouchThree = window.matchMedia && window.matchMedia("(pointer:coarse)").matches;
var isDesktopIE = !!window.MSInputMethodContext && !!document.documentMode && !isTouchTwo;
var uaDataIsMobile = window.navigator.userAgentData && window.navigator.userAgentData.mobile;
var isDevice = typeof uaDataIsMobile === 'boolean' ? window.navigator.userAgentData.mobile || (isTouchTwo && isTouchThree) : ((/android|avantgo|blackberry|googlebot-mobile|iemobile|opera mini|kitkat|palmos|bolt|boost|cricket|docomo|fone|hiptop|mini|mobi|palm|iphone|ipod|phone|ipad|pie|tablet|silk|up\.browser|up\.link|playbook|webos|wos/i.test(window.navigator.userAgent.toLowerCase()) && !isDesktopIE) || window.navigator.platform === 'MacIntel' && isTouch);

console.log('1. '+isTouch+' 2. '+isTouchTwo+' 3. '+isTouchThree+' 4. '+/android|avantgo|blackberry|googlebot-mobile|iemobile|opera mini|kitkat|palmos|bolt|boost|cricket|docomo|fone|hiptop|mini|mobi|palm|iphone|ipod|phone|ipad|pie|tablet|silk|up\.browser|up\.link|playbook|webos|wos/i.test(window.navigator.userAgent.toLowerCase())+' 5. isDevice: '+isDevice)

Addresses concerns regarding a) the claim by IE11 desktop navigator.userAgent string to be "tablet", and b) the similarity between iPadOS User Agent in Safari and MacOS Catalina. (Not personally tested, but logical reasoning suggests this.

quote

Visit here for more information.

unquote

This solution is expected to function effectively. My reliance is placed on its performance. (Refer to edit section.)

Take into account that my response aligns with Client Hints. (I believe future responses should adhere to this as well.) For browsers supporting navigator.userAgentData, there will be no necessity for navigator.userAgent.

Apologies for the lengthy code strings. They appear much neater in ES6 format.

To carry out a media query, apply a style sheet based on the output of true or false.

edit: How to identify iPad and iPad OS version in iOS 13 and above?

if (navigator.maxTouchPoints > 1) {
  // browser supports multi-touch
}

I previously thought it was > 0. (Corrected within the code snippet.)

Answer №14

After extensive testing across multiple browsers, I discovered that in order to ensure compatibility, it is necessary to utilize both hover and pointer features -

@media (hover:none), (pointer:coarse){   
  .show_on_touch {display:inline}
}

The statement hover:none indicates lack of hover support, however some browsers may not accurately report this information.

Additionally, pointer:coarse signifies the absence of precise pointer control, suggesting touch-based interaction.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips on creating type definitions for CSS modules in Parcel?

As someone who is brand new to Parcel, I have a question that may seem naive. In my project, I am using typescript, react, less, and parcel. I am encountering an error with typescript stating 'Cannot find module 'xxx' or its corresponding t ...

Conceal information within a label

I am encountering an issue with a wordpress plugin and I am attempting to conceal (or alternatively, replace which would be fantastic) the terms "DD", "MM" and "YYYY" in the provided code: <div class="smFormInlineFormCont"> <div class="smInli ...

Customizing the field_error_proc in Rails is causing issues with the HTML layout

Within a rails application, I have customized the field_error_proc to enable inline error displays as shown below: https://i.sstatic.net/DjmdN.png The code snippet for achieving this functionality is outlined here: ActionView::Base.field_error_proc = pr ...

Can you propose a different approach to creating the "word stack" that overcomes the limitations of my current method?

I am attempting to convert a set of two radio buttons into a stack of two labels, one blue and one gray, to represent the selected radio button and the unselected one. Clicking on this stack will toggle which label is blue (and consequently which radio but ...

"Aligning the title of a table at the center using React material

I have integrated material-table into my react project and am facing an issue with centering the table title. Here is a live example on codesandbox: https://codesandbox.io/s/silly-hermann-6mfg4?file=/src/App.js I specifically want to center the title "A ...

The HR element seems to be fixed in place and is not moving

I'm having trouble figuring out what's causing the issue, so I wasn't sure how to title it. Any help in looking at the code would be greatly appreciated. Here is the problem: https://i.sstatic.net/b73CA.jpg The HR tag should be positioned ...

Background and border presentation issues arising from CSS conflict

While working on a webpage, I encountered a design conflict within a div that contains a group of other div elements. The current appearance can be seen at , and the desired look is shown in the image here: enter image description here ...

I am unable to make any changes to the .navbar and #navbar elements using CSS

I'm having trouble customizing the navigation bar using .navbar and #navbar in CSS. I was hoping to make changes to the Bootstrap navbar, but nothing seems to be working. I'm not sure if it's an issue with the HTML or CSS. I've include ...

Tips for aligning a div below another div nested within a separate container

Can I position div#d2 directly beneath the div#d1 container according to the code below, instead of positioning it outside the height of the wrapper? #wrapper { height: 100%; display: flex; background-color: steelblue; align-items: center; min ...

Tips for positioning a background image behind page content

I have a webpage with a background image, and now I want to add content that floats over it. However, the code below is placing the content behind the image. How can this be corrected? It's important to note that I'm attempting to achieve the ef ...

Unable to generate file with Compass

In my attempts to compile a project using compass, I have experimented with both the gui app and the command line. However, I consistently encounter the same error message in both cases: "Nothing to compile. If you're trying to start a new project, yo ...

Arrange two divs on either side of the center div when on a smaller screen

Looking for a straightforward approach to achieve this. Imagine it as follows: [A][__B_][A] to [A][A] [__B_] I hope that explanation is clear, but I'm happy to provide more details if necessary. Thank you in advance! ...

Place the text (menu) adjacent to the navigation bar

I am currently using bootsrap 4 alpha 6 in combination with midnight.js to alter the color of my navigation menu toggler. I am trying to incorporate a text element (MENU) alongside it, similar to the example shown in the Capture image. For the text toggler ...

Is it a good idea to relocate the pagination to the top of the DataGrid in MUI

Can someone suggest a solution for moving the default pagination of XGrid above the table? Or do I need to develop my own custom pagination instead of using the built-in feature with XGrid? ...

Alter attribute with an impact

I am looking for a solution to switch the image source using attr, while also incorporating a fade effect in the process. I have attempted to implement one of the suggestions from another post, but it is not producing the desired outcome. Current Appearan ...

How to position collapsible buttons in Twitter's Bootstrap framework

I have successfully created two buttons on the same line. The second button is collapsible and when clicked, it adds a row of two more buttons to the view. However, the newly collapsed row of buttons appears aligned with the second button. I would like th ...

Tips for creating horizontal dividers with CSS in Vuetify using <v-divider> and <v-divider/> styling

Currently, I am working on a project using Vue.js and adding Vuetify. However, I need to use a component. .horizontal{ border-color: #F4F4F4 !important; border-width: 2px ; } <v-divider horizontal class=" horizontal ...

Challenge with CSS Box Shadow

Hey there, I've been attempting to add a shadow effect to a box inside another box but I'm struggling to achieve the desired outcome. <div class="box effect2"> <div class="box effect2"> Box inside a box <div> &l ...

Unable to retrieve data from the database within PHP code

I have successfully built a shopping cart website utilizing SQL, HTML, and PHP. Below is the code snippet for the 'Add to Cart' button: <form method="post" action="cart.php" class="form-inline"> <input type="hidden" value="&apos ...

Achieving full opacity text within a semi-transparent div: a simple guide

Within my div, I have an a tag. I applied opacity:0.5 to the div, causing the text inside to also appear at 0.5 opacity. I am looking for a way to have the text display with opacity:1 inside my div that has an overall opacity of 0.5, without resorting to ...