Ensure accurate interpretation of CSS3 transform percentages on Android devices

tl;dr? Looking for a way to enable GPU acceleration on Android Chrome & default browser for the mechanism shown in the link below.

UPDATE 2 (2014-01-13 13:25:30Z): As per bref.it's comment, the issue was resolved with Android 4.4 KitKat but my previous fix now breaks it!

UPDATE 1 (2012-11-01 17:54:09Z): The problem seems to be related to the transformation matrix reported by the computed style of the transformed element, which returns a pixel value. Will attempt to create a Modernizr test to explore potential solutions.

I have devised a method to slide a container to reveal horizontally aligned sub-sections, essentially sliding tabs. To minimize the use of JavaScript and utilize CSS for stylistic aspects, I have kept the JS involvement minimal by only modifying an attribute on the wrapper:

(w/ left)

http://jsfiddle.net/barney/VPJuq/ (on mobile devices, append /show/ to the fiddle URL to view the results independently)

Explanation on how this operates: treating the tabs as inline-block elements allows me to specify white-space: nowrap (remaining code collapses whitespace between tabs) and stack them horizontally without clearing or returning while maintaining full width within their parent. Additionally, setting a negative left offset to the wrapper achieves the desired effect. Pretty neat, isn't it?

Providing some context: the interface is intended for native mobile applications where core functionality relies on cutting-edge mobile-specific technology through a UIWebView, currently supported only on Android.

The primary issue is that transform: translate works smoother than left or margin-left transitions, especially on Android where non-translated transitions are sluggish even on modern devices with the latest OS versions. However, Android appears to interpret the box model differently when utilizing translate. For demonstration, here's a transform-based version that functions similarly to the earlier example and works on browsers supporting translate3d...

(w/ translate)

http://jsfiddle.net/barney/EJ7ve

When tested on iPhone or Firefox on Android, improved frame rates are observed. Yet, on Chrome and the default Android browser, the translateX offset of -100% refers to the entire space occupied by all three tabs, resulting in the wrapper sliding partially, making none of the tabs visible. This discrepancy is puzzling as transform percentages should relate to the full box model of the element being transformed based on computed styles.

Is this behavior best described as a bug?

No pure-CSS approach seems viable for identifying and resolving this issue. One potential solution involves selectively applying rules based on the User-Agent string for Android, which unfortunately limits cross-browser compatibility. Another workaround could involve adjusting the percentage calculations specifically for Android, although this may lead to browser-specific behavior and entail knowing the number of tabs in advance.

(w/ translate — for Android update: unnecessary and breaks on Android 4.4 KitKat)

http://jsfiddle.net/barney/nFt5t/

Despite these efforts, the problem persists under certain conditions such as orientation changes, where the offset behaves correctly in other browsers but not consistently in Android. Experimentation with applying translations directly to the tabs yielded no improvement, particularly on Android's browser.

(w/ translate, working on Android's theory, not working on Android at all)

http://jsfiddle.net/barney/EJ7ve/9

Your insights or suggestions for a comprehensive cross-browser resolution would be greatly appreciated.

Answer №1

While I am on Android 2.3 and cannot replicate the exact issue you mentioned (related to your remark about "-100% somehow referring to the space occupied by all three tabs"), I faced some other irregularities leading to sporadic/jerky transitions and various odd behaviors that I did not thoroughly investigate.

Let's assume, for discussion purposes, that the "wrapper" has a width of 500px.

Through the utilization of your inline-block/nowrap approach (a layout technique from YUI that is often overlooked), the horizontal space taken up by your 3 tab panels amounts to 1500px. As per your explanation, it seems necessary to deceive the browser into perceiving that all tab panels collectively occupy only 500px of horizontal space. Refer to my fiddle, where I employ negative margins and translations as a workaround aimed at tricking the browser in a manner that should theoretically be effective, although I cannot verify this. Nonetheless, my example resolved the odd behavior I encountered on Android 2.3 - thus, you might consider utilizing it regardless.

http://jsfiddle.net/ryanwheale/EJ7ve/29/

(and the pertinent CSS)

.tabs > * {
    width: 100%;
    margin-left: -100%;
}
.tabs > *:first-child {
    -webkit-transform: translate3d(0%, 0, 0);
    -moz-transform: translate3d(0%, 0, 0);
    -ms-transform: translate3d(0%, 0, 0);
    -o-transform: translate3d(0%, 0, 0);
    transform: translate3d(0%, 0, 0);
}
.tabs > *:first-child + * {
    -webkit-transform: translate3d(100%, 0, 0);
    -moz-transform: translate3d(100%, 0, 0);
    -ms-transform: translate3d(100%, 0, 0);
    -o-transform: translate3d(100%, 0, 0);
    transform: translate3d(100%, 0, 0);
}
.tabs > *:first-child + * + * {
    -webkit-transform: translate3d(200%, 0, 0);
    -moz-transform: translate3d(200%, 0, 0);
    -ms-transform: translate3d(200%, 0, 0);
    -o-transform: translate3d(200%, 0, 0);
    transform: translate3d(200%, 0, 0);
}
.tabs > *:first-child + * + * + * {
    -webkit-transform: translate3d(300%, 0, 0);
    -moz-transform: translate3d(300%, 0, 0);
    -ms-transform: translate3d(300%, 0, 0);
    -o-transform: translate3d(300%, 0, 0);
    transform: translate3d(300%, 0, 0);
}

Note: Experimented with relative positioning instead of the above transforms, but encountered the same peculiarities as previously described.

Answer №2

I encountered a comparable problem.

In my case, the issue stemmed from:

* {
    box-sizing: border-box;
}

Having applied border-box to all elements was causing the percentage translate3d to not work correctly. After removing it, the issue was resolved.

Answer №3

If your CSS is not functioning as expected, try implementing a workaround. Take a look at the modified version I created:

http://jsfiddle.net/EG9v8/1/

function adjustCss(index){
    // Calculate the offset based on the size of the tabs
    var size = -$('.tabs').width() * index;
    // Generate styles for the specified offset.
    var css = '-webkit-transform: translate3d('+size+'px, 0, 0);';
    css += '-moz-transform: translate3d('+size+'px, 0, 0);';
    css += '-ms-transform: translate3d('+size+'px, 0, 0);';
    css += '-o-transform: translate3d('+size+'px, 0, 0);';
    css += 'transform: translate3d('+size+'px, 0, 0);';
    return css;
}

$('.tabLinks a').on('click', function(e){
    e.preventDefault();

    var index = $(this).index();

    // Apply the updated style
    $('.tabs').attr('style', adjustCss(index));
});

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

Adjust the left and right margins while maintaining the vertical margin spacing

Is there a way to apply horizontal margin while inheriting vertical margin without explicitly setting margin-left and margin-right? I was hoping for something like margin: inherit 20px; to be effective. Take a look at the example here: https://jsfiddle.ne ...

Enhanced slider functionality with the addition of multiple slick transitions

My layout features a question with 4 options. When any answer is clicked, a new slide is added and the layout transitions to that slide. $(document).on('click', '.goal1 li', function(e){ $(this).addClass('goal-selected'). ...

search for the compose function in the material table within a react component

When I receive a string array as a response from the API for lookup, it looks like this: ['India', 'Sri Lanka'] I am looking to pass this as a parameter to a Material React table column as a List of Values (LOV) in the following format ...

Enhance the appearance of specific wordpress usernames by adding a touch of "flair" next to them

I'm looking to add a special "flair" next to specific users on my WordPress website, similar to how YouTube distinguishes verified users. I have the CSS for changing the color on hover, but I need help keeping it positioned correctly. Examples from Y ...

Choosing between JavaScript and Handlebars.js depends on the specific needs

Can anyone explain the advantages of utilizing Handlebars.js or similar libraries over solely relying on JavaScript? Thus far, I haven't come across any functionality in Handlebars that cannot be achieved with just pure JavaScript. ...

Tips for customizing the checked color of Material UI Radio buttons

If I want my radio button to be green instead of the default options (default, primary, secondary), how can I achieve that? I attempted to override the color using the classes prop like this: const styles = theme => ({ radio: { colorPrimary: { ...

Achieving Vertical Alignment of DIV and Text Using Bootstrap 4

After scouring through various questions, articles, and Bootstrap 4 documentation, I have yet to find the solution I am seeking. DEMO: https://jsfiddle.net/zxLLqsm0/ My goal is to create boxes with uniform height for all columns while vertically aligning ...

Different browsers have varying ways of handling transition end callbacks with AddEventListener()

Each browser has its own transition end callback. Therefore, I find myself needing to use addEventListener() for each one. addEventListener('transitionend', function() { // code here }); addEventListener('webkitTransitionEnd', funct ...

Sending an Image from Activity to Adapter Class

In the process of transferring an image from SingleItem activity to CartAdapter, I encountered difficulty when trying to pass the item's image. Whenever a user clicks on the Add to Cart button in SingleItem activity, it is necessary to send the item ...

What is the best way to implement "ng-" to function smoothly with all attributes?

Is there a generic attribute like ng-enabled, ng-src, ng-class that can work for any attribute (ng-x)? For instance, here is the code snippet: <div ng-attrbuite1="a" ng-otherattribute="b"></div> I wish to achieve the following output: <d ...

Requires a minimum of two page refreshes to successfully load

Our website is currently hosted on Firebase. However, there seems to be an issue as we have to refresh the website at least twice in order for it to load when visiting www.website.com. Update: We are unsure of what could be causing this problem. W ...

Error encountered when attempting to initiate a second screenshare on Chrome due to an invalid state

I am interested in utilizing Screensharing in Chrome. After following a guide and creating an extension to access the deviceId for getUserMedia, I was able to successfully start streaming my screen. However, when I attempted to stop the stream using the pr ...

Using AutoCompleteTextView results in the disappearance of items in the ListView

I am currently working on the Extra Credit portion of the Adding a List tutorial in Android Tutorials. I have encountered an issue while trying to populate the AutoCompleteTextView with items from the ArrayAdapter. When the addr field contains characters a ...

Is there a way to sort tables in jQuery while keeping rows together?

I am working with a table that includes a header and footer, as well as multiple columns containing numeric data. I am looking to implement a feature that allows the end user to click on a column header or footer to sort the rows in the table based on that ...

Attaching the CSS file to the Haml layout template

I'm currently working on linking a css file to a haml layout template Within the ApplicationHelper class, I have a method to properly generate html module ApplicationHelper def styletag(sheet_name) "<link rel='stylesheet' href=&a ...

Seek out the most fundamental term to describe a specific callback

I'm transitioning from the embedded world to Kotlin and I'm still getting the hang of things. I'm aware that there is a mechanism I can inherit and utilize in my class, but I'm not exactly sure what this mechanism is called in the conte ...

Initiate ajaxForm submission again if necessary

Utilizing the ajaxForm function to transmit data to a PHP background process while some JavaScript functions monitor the asynchronous operation. In cases of failure, such as internet or electricity disruptions, I want users to have the ability to retry the ...

Angular 6: Issue TS2339 - The attribute 'value' is not recognized on the 'HTMLElement' type

I have a textarea on my website that allows users to submit comments. I want to automatically capture the date and time when the comment is submitted, and then save it in a JSON format along with the added comment: After a comment is submitted, I would li ...

Requesting data from an ASP.NET MVC web API using an Ajax call

I have been working on an MVC app and trying to establish an AJAX connection to a web API controller. However, the error message that keeps appearing is "Unidentified". Additionally, when I attempt to throw a random exception in my api controller delete ac ...

Upon clicking a button on page 1, the data is transmitted to page 2 before redirecting the user to page 3

When a user enters information into a text field on page1.php and clicks the submit button, the data is sent to page2.php where it is used to query a database and save it in an XML file. <Form name="search_form" method="POST" action="page2.php"> ...