Writing an extension for a Plugin I have the possibility to change all attributes of an HTML element using PHP.
$attributes["style"] .= 'padding-left:10px;';
array_push($attributes["class"], "long-container");
array_push($attributes["class"], "super smooth");
$attributes["data-whatever"] = "great";
Now I want to give a user the possibility to enter the width / height ratio of a div dynamically (the solution of how to do this is described in the answer by @Web_Designer here: Maintain the aspect ratio of a div with CSS).
Within the function where I can change the output of the third-party Plugin I wrote the following code for calculating the width height ratio according to the input. As the height of my boxes is :
if( !empty( $args['stretchy-desktop'] ) ) {
$sd = array_map('trim',explode(":",$args['stretchy-desktop']));
if(count($sd)==2) {
$sd[0] = floatval(str_replace(",",".",$sd[0]));
$sd[1] = floatval(str_replace(",",".",$sd[1]));
if($sd[0]>0 && $sd[1]>0) {
$padding = ($sd[1] / $sd[0])*100;
array_push($attributes['class'], 'stretchy-desktop');
$attributes['style'] .= 'padding-bottom:'.$padding.'%;';
}
}
}
Great right? However now the user wants a possibility to enter a different weight height ratio for mobile devices as well as a different dynamic min-height for mobile devices and this is there I am stuck.
1) It is not possible to give inline @media queries right now otherwise my solution would be like this (Is it possible to put CSS @media rules inline?):
$attributes['style'] .= '@media (min-width:540px) {padding-bottom:'.$padding.'%;}@media (max-width:539px) {padding-bottom:'.$padding_mobile.';}';
2) It is not possible to use HTML attribute values in CSS right now (CSS values using HTML5 data attribute) otherwise my solution would be like this:
$attributes['data-desktoppadding'] = $padding;
$attributes['data-mobilepadding'] = $padding_mobile;
In CSS:
@media (min-width:540px) {
.long-container {
padding-bottom: attr(data-desktoppadding);
}
}
@media (max-width:539px) {
.long-container {
padding-bottom: attr(data-mobilepadding);
}
}
3) As the values are dynamic numbers I can not define a CSS class for every possible existing float.
Of course I could use JavaScript but we all know the significant drawbacks (including ugly page load).
Can you think of any CSS solution for this dilemma?
Here is a solution I came up with. It involves creating a wrapper div around the target element. Basically, the way that this works is that the outer div is assigned the inline styles for the mobile mode, and the inner div is assigned the inline styles for desktop mode. When the browser window is resized to be below the threshold for desktop view, it resets the inner div's (desktop) inline styles to defaults so the outer div's (mobile) inline styles take over. When the browser window is resized to be above the threshold, it resets the outer div's (mobile) inline styles to defaults so the inner div's (desktop) inline styles take over. The way that it overrides the inline styles is by using the !important
keyword in the rulesets in the CSS media queries.
I think it goes without saying that the inline styles in the snippet below would be replaced with your $attributes['style']
. But since you will have separate mobile and desktop styles, I guess it would be $attributes['style-mobile']
and $attributes['style-desktop']
.
@media (min-width:540px) {
.padding-mobile {
padding-bottom:0 !important;
width: auto !important;
}
}
@media (max-width:539px) {
.padding-desktop {
padding-bottom:0 !important;
width: auto !important;
}
}
<div class="padding-mobile" style="width:100%;background-color:red;padding-bottom:100%;">
<div class="padding-desktop" style="width:50%;background-color:red;padding-bottom:25%;">
</div>
</div>
An elegant approach that works in most major browsers is the usage of custom properties. They are basically variables in CSS. As of writing this (2017-03-27), only IE and Edge do not support this, although they are working on support for Edge.
You would add the variables to the $attributes['style']
and actually apply them in the stylesheet inside a media query. They are then used dynamically by the browser.
I have implemented a demo as a snippet, but because it is easier to change the viewport size on JSFiddle, also a copy of the demo there. Note that the responsive breakpoint is defined in CSS here, and the variables are defined in inline styles of the element.
.container {
width: 200px;
}
.block {
position: relative;
display: block;
box-sizing: border-box;
width: 100%;
height: 0;
padding: 10px;
padding-bottom: var(--desktop-ratio);
background: #bada55;
color: #444;
}
@media (min-width: 540px) {
.mobile {
display: none;
}
}
@media (max-width: 539px) {
.desktop {
display: none;
}
.block {
padding-bottom: var(--mobile-ratio);
}
}
<div class="container">
<div class="block" style="--desktop-ratio: 56.25%; --mobile-ratio: 200%;";>
My aspect ratio is set via custom properties. It is <span class="mobile">1:2</span><span class="desktop">16:9</span>.
</div>
</div>
It is (at least at the moment) apparently not possible to set a breakpoint using a variable. That is,
@media (min-width: var(--breakpoint)) { ... }
is apparently not understood by at least Firefox and Chrome at the moment.
Alternatively, building on Kodos Johnson's answer: if you have only a single breakpoint, you can make use of the padding-bottom
and padding-top
. One of the two defines the aspect ratio on small screens, and the other defines it on big screens. This removes the need to add a wrapper element. Here is an example, based on the one from Kodos' answer.
@media (min-width:540px) {
.block {
padding-top: 0 !important;
}
}
@media (max-width:539px) {
.block {
padding-bottom: 0 !important;
}
}
<div class="block" style="width: 50%;
padding-bottom: 25%;
padding-top: 100%;
background-color: red;">
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With