I am working on a layout for a Blazor Webassembly component. (=Fat browser client, no server rendering)
The layout looks like this and works as expected:
.grid
{
min-height: 100vh;
min-width: 100vw;
height: 100vh;
width: 100vw;
background-color: black;
display: grid;
grid-template-rows: 10px 5vh calc(90vh - 20px) 5vh 10px;
grid-template-columns: 10px 3vw calc(94vw - 20px) 3vw 10px;
/*Blazor Special*/
margin: -8px;
}
.gridCellLogo
{
grid-column-start: 2;
grid-column-end: 2;
grid-row-start: 2;
grid-row-end: 2;
background-color: red;
}
<div class="grid">
<div class="gridCellLogo">
#*Put your component here*#
</div>
</div>
However, if I use CSS variables, they are not applied. Look at --somecolor
:host
{
--somecolor: green;
}
.grid {
min-height: 100vh;
min-width: 100vw;
height: 100vh;
width: 100vw;
background-color: var(--somecolor);
display: grid;
grid-template-rows: 10px 5vh calc(90vh - 20px) 5vh 10px;
grid-template-columns: 10px 3vw calc(94vw - 20px) 3vw 10px;
/*Blazor Special*/
margin: -8px;
}
My question:
Is my CSS wrong or is Blazor Webassembly not ready for CSS variables yet?
Are you using Blazor CSS Isolation? E.g., MyComponent.razor.css? If so, CSS Isolation does not support pseudo classes, variables, or any CSS that starts with a single colon :.
You will need to declare these variables in a non-compiled CSS file like the app.css under wwwroot/css.
Blazor css Isolation doesn't use shadow DOM so the :host selector is not available.
You can define your variables on the :root selector and then override it with your custom value on a particular css class like this
<div class="grid my-warpper-class">
<div class="gridCellLogo">
#*Put your component here*#
</div>
</div>
:root
{
--somecolor: red;
}
.my-wrapper-class
{
--somecolor: green;
/* blue here is a fallback in case --somecolor didn't exist */
background-color: var(--somecolor, blue);
}
.gridCellLogo {
background-color: var(--somecolor, green);
}
defining the --somecolor variable on the :root will make it available everywhere, when you can overwrite it in any other class like my-wrapper-class
in that case the wrapper class and the gridCellLogo will have different background colors
Related
started to learn HTML and CSS, I want 4 blocks, 2 centred and 1 on each side, left and right. And if resize the window the block distance between the outer and inner blocks varies and the borders never cut each other
this is the full css code, I have the feeling I did this way too complicated.. I mean it works but yeah..
section {
display: inline-block;
position: relative;
width: 100vw;
height: 100vw;
background-color: blue;
}
.hm {
display: inline-block;
position: fixed;
top: 50%;
padding: 20px;
margin: 20px;
border: 10px solid yellow;
width: 60px;
height: 60px;
transform: translateX(-25%); translate: 10px;
}
.hm0 {
display: inline-block;
position: fixed;
top: 50%;
left: 50%;
padding: 20px;
margin: 20px;
border: 10px solid red;
width: 60px;
height: 60px;
transform: translate(-20px);
}
.hm1 {
display: inline-block;
position: fixed;
top: 50%;
left: 50%;
padding: 20px;
margin: 20px;
border: 10px solid rgb(211, 208, 208);
width: 60px;
height: 60px;
transform: translate(-100%); translate: -20px;
}
.hm2 {
display: inline-block;
position: fixed;
top: 50%;
right: 0;
padding: 20px;
margin: 20px;
margin-left: auto;
margin-right: 0;
border: 10px solid rgb(255, 0, 225);
width: 60px;
height: 60px;
}
<body>
<section>
<div class="hm"></div>
<div class="hm0"></div>
<div class="hm1"></div>
<div class="hm2"></div>
</section>
</body>
I am not sure if this is what you are going for, but I have attempted to recreate it with Flexbox.
First, I wrapped the blocks that should be in the center in another div as follows:
<section>
<div class="hm box"> </div>
<div class="center">
<div class="hm0 box"> </div>
<div class="hm1 box"> </div>
</div>
<div class="hm2 box"></div>
</section>
I also added a class box that will contain the height and width of each box.
With that, I styled them like so:
section {
display: flex;
justify-content: space-between;
align-items: center;
width: 100vw;
height: 100vw;
background-color: blue;
}
.center {
display: flex;
}
.hm {
border: 10px solid yellow;
}
.hm0 {
border: 10px solid red;
}
.hm1 {
border: 10px solid rgb(211, 208, 208);
}
.hm2 {
border: 10px solid rgb(255, 0, 225);
}
.box {
width: 60px;
height: 60px
}
The most important styles concerning the layout are here:
section {
display: flex;
justify-content: space-between;
align-items: center;
width: 100vw;
height: 100vw;
background-color: blue;
}
display: flex;: aligns all blocks horizontally(except the blocks in the .center div, because they are not the section element direct children)
justify-content: space-between;: this pushes the first and last blocks to the edges of the section element, leaving the center div elements in the center.
align-items: center;: aligns all the horizontal blocks in the center of the section element.
Now since the blocks in the center div are not direct descendants of section element, I also used display:flex to align them horizontally:
.center {
display: flex;
}
To learn more about flexbox and its properties, check out flexboxfroggy
You can checkout the demo of the code here:
https://jsfiddle.net/stanulilic/s7oh4nv9/
To re-write your posted CSS in a more concise form leads us to the following, explanatory comments are in the CSS:
/* this is a personal style or affectation that I tend to list
CSS properties alphabetically, that way if you're looking to
see if a property is set I know where to find it, and if it's
not where I expect it to be I know it hasn't been set on that
element/selector. This is a personal style, it's not mandatory
it's probably not even 'best-practice,' but you'll help yourself
if you pick a particular approach and then stick with it: */
section {
background-color: blue;
display: inline-block;
height: 100vw;
position: relative;
width: 100vw;
}
/* the following selector matches the four <div> elements within the
<section> element, and the child combinator (the '>') prevents the
selector matching any <div> elements nested within those child
elements. This selector then applies all common CSS styles for all
the child elements, to avoid redeclarations: */
section > div {
/* all <div> elements have a 10px solid border, so here we apply
that border with the color set to 'transparent,' allowing us to
set the 'border-color' in the individual elements: */
border: 10px solid transparent;
display: inline-block;
height: 60px;
padding: 20px;
margin: 20px;
position: fixed;
top: 50%;
width: 60px;
}
.hm {
/* setting the border-color for this specific element: */
border-color: yellow;
/* the following translations were combined into one
'translate' declaration, using the calc() method:
transform: translateX(-25%);
translate: 10px;
*/
translate: calc(-25% + 10px);
}
.hm0 {
/* again, setting properties specific to the individual elements: */
border-color: red;
left: 50%;
translate: -20px;
}
.hm1 {
border-color: rgb(211, 208, 208);
left: 50%;
/* combining the two different translations into one single declaration
via translate: calc(...):
transform: translate(-100%);
translate: -20px;
*/
translate: calc(100% - 20px);
}
.hm2 {
border-color: rgb(255, 0, 225);
margin-left: auto;
margin-right: 0;
right: 0;
}
<section>
<div class="hm"></div>
<div class="hm0"></div>
<div class="hm1"></div>
<div class="hm2"></div>
</section>
JS Fiddle demo.
Things to learn from the above snippet/approach:
try to group all common styling together under one selector that can apply to the each element of a group as a whole, two
use the same properties to do the same thing; don't combine functions and properties such as – for example – transform: translate() (or translateX()) with translate,
if you find you're having to use a property/function and then use a different property/function to further adjust, consider looking for a way to combine the two adjustments into one (the calc() function being a much-used, and versatile, way of doing so),
try and adopt an approach of organising your code in such a way that it becomes easy and predictable to find a property-value pair in your code, particularly CSS, where it's incredibly easy to just add amendments or additions to the end of a rule-set.
Now, the above layout can be achieved more easily using either CSS flex layout, or CSS Grid.
First, flex-box:
/* a simple CSS reset, to ensure all browsers size elements the same way,
using the border-box algorithm, to include borders and padding in the
declared sizing: */
*,
::before,
::after {
box-sizing: border-box;
/* removing browser-default margins and padding: */
margin: 0;
padding: 0;
}
section {
/* here we align the items within the <section> to the
vertical center; align-items works on the cross-axis
which is perpendicular to the main-axis; the main-
axis default is 'row' (so horizontal), therefore by
default 'align-items' positions the flex-items (the
elements within the flex-box) on the vertical axis:*/
align-items: center;
background-color: blue;
block-size: 100vh;
/* specifying the flex-layout: */
display: flex;
/* positioning elements to the center on the main-axis,
horizontal by default: */
justify-content: center;
}
section > div {
/* ensures that the element's width and height are equal: */
aspect-ratio: 1;
/* defining the borders of all elements matched by the
selector: */
border: 10px solid transparent;
/* defining the block-size of the matched elements; this is
a CSS logical property, and in European languages - and
others descended from those languages - is equivalent to
'height'; and the previous use of 'aspect-ratio'
automatically sets the 'inline-size' (equivalent to 'width'
in European languages and their descendants): */
block-size: 60px;
padding: 20px;
}
.hm {
border-color: yellow;
/* to move this element as far as possible to the inline-start
(the left, for European languages) we use the following to
add an auto-sized margin to the inline-end (in European
languages that's the 'right') side: */
margin-inline-end: auto;
}
.hm0 {
border-color: red;
}
.hm1 {
border-color: rgb(211, 208, 208);
}
.hm2 {
border-color: rgb(255, 0, 225);
/* as above - for .hm - we want to move this element to the
inline-end (the 'right,' in European languages...) side,
so we again set an auto margin on the opposing side, the
'inline-start' ('left,' in European languages): */
margin-inline-start: auto;
}
<section>
<div class="hm"></div>
<div class="hm0"></div>
<div class="hm1"></div>
<div class="hm2"></div>
</section>
JS Fiddle demo.
And, finally, CSS Grid layout:
/* a simple CSS reset, to ensure all browsers size elements the same way,
using the border-box algorithm, to include borders and padding in the
declared sizing: */
*,
::before,
::after {
box-sizing: border-box;
/* removing browser-default margins and padding: */
margin: 0;
padding: 0;
}
section {
align-items: center;
background-color: blue;
block-size: 100vh;
/* specifying the flex-layout: */
display: grid;
grid-template-columns: repeat(4, 1fr);
}
section > div {
/* ensures that the element's width and height are equal: */
aspect-ratio: 1;
/* defining the borders of all elements matched by the
selector: */
border: 10px solid transparent;
/* defining the block-size of the matched elements; this is
a CSS logical property, and in European languages - and
others descended from those languages - is equivalent to
'height'; and the previous use of 'aspect-ratio'
automatically sets the 'inline-size' (equivalent to 'width'
in European languages and their descendants): */
block-size: 60px;
padding: 20px;
}
/* selecting the odd-numbered <div> elements within the <section>,
the first and third: */
section > div:nth-child(odd) {
/* positioning them to the inline-start by setting their
margin-inline-end (right, in European languages...) to
'auto': */
margin-inline-end: auto;
}
/* selecting the even-numbered <div> elements within the <section>,
the second and fourth: */
section > div:nth-child(even) {
/* positioning them to the inline-end, by setting the opposing
margin - margin-inline-start - to auto: */
margin-inline-start: auto;
}
.hm {
border-color: yellow;
}
.hm0 {
border-color: red;
}
.hm1 {
border-color: rgb(211, 208, 208);
}
.hm2 {
border-color: rgb(255, 0, 225);
}
<section>
<div class="hm"></div>
<div class="hm0"></div>
<div class="hm1"></div>
<div class="hm2"></div>
</section>
JS Fiddle demo.
References:
align-content.
align-items.
aspect-ratio.
background-color.
block-size.
border.
border-color.
box-sizing.
calc().
CSS Logical Properties.
display.
grid-template-columns.
height.
inline-size.
justify-content.
justify-items.
margin.
margin-block.
margin-block-end.
margin-block-start.
margin-inline.
margin-inline-end.
margin-inline-start.
padding.
padding-block.
padding-block-end.
padding-block-start`.
padding-inline-end.
padding-inline-start.
place-items.
repeat().
transform.
translate (CSS property).
translate() (CSS function).
width.
I need to achieve something like that:
where this grey square is actually an image, that can be changed.
it has to be done by background, I cannot place simply img there.
I tried to achieve this with linear gradient, which will be easy if I can just set the background for specific area, but the fact that the what you can see in the image below it is just right 50% of the background complicates this. I tried different solutions for some time and I am clueless.
You could use CSS grid to get the visuals in your image:
const img = document.getElementById('img')
img.style.backgroundImage = "url('http://placekitten.com/200/300')"
html,
body {
margin: 0;
padding: 0;
}
body {
height: 100vh;
}
.container {
height: 100%;
width: 100%;
background: gray;
display: grid;
grid-template-columns: 1fr 10px 50%;
grid-template-rows: 1fr calc(50% - 10px) 50px 10px 1fr
}
.img-wrapper {
grid-column: 3 / 3;
grid-row: 2 / 4;
background: red;
background-size: cover;
background-position: center;
background-repeat: no-repeat
}
.partial-border {
grid-column: 2 / 4;
grid-row: 3 / 5;
background: blue;
}
<div class="container">
<div class="partial-border"></div>
<div id="img" class="img-wrapper"></div>
</div>
The 'Slide' button toggles a left-margin. Need to find a way to animate that left-margin however using a transition on any calced element seems to be bugged in IE11 - still.
Sample in JS Bin
https://jsbin.com/qirozodete/1/edit?html,css,output
and below.
This is a very simple mock up of the project I'm working on. Trying to create an element that slides & shrinks 1 grid column at every resolution. Currently using a calc to work out how big a grid column is, which works on FF/Chrome/Safari. Just not IE.
Don't think I can use transform: translate either as the element wouldn't shrink, and the calcs needed are a bit more complex than just stacking translates.
Any idea would be appreciated.
document.getElementById('slide-btn').addEventListener('click', function() {
document.getElementById('grid').classList.toggle('slide');
})
button {
background: white;
border: 1px solid black;
padding: 5px 10px;
}
#grid {
display: -ms-grid;
-ms-grid-columns: 1fr 1fr 1fr 1fr;
}
#grid-item-1 {
background: teal;
-ms-grid-column: 1;
-ms-grid-column-span: 2;
height: 150px;
transition: margin-left 500ms ease-in;
}
#grid.slide #grid-item-1 {
margin-left: calc(100vw / 4);
}
<button id="slide-btn">Slide</button>
<div id="grid">
<div id="grid-item-1"></div>
</div>
I tested your code and reproduced the issue. I think we can only use JavaScript to make changes as a workaround in IE. We can calculate the value of clientWidth and toogle the marginLeft value.
Sample code:
document.getElementById('slide-btn').addEventListener('click', function() {
var ml = document.getElementById("grid-item-1").style.marginLeft;
var vw = (document.documentElement.clientWidth) / 4;
if (ml == "") {
document.getElementById("grid-item-1").style.marginLeft = vw + "px";
} else {
document.getElementById("grid-item-1").style.marginLeft = "";
}
})
button {
background: white;
border: 1px solid black;
padding: 5px 10px;
}
#grid {
display: -ms-grid;
-ms-grid-columns: 1fr 1fr 1fr 1fr;
display: grid;
grid-template-columns: repeat( 4, 1fr);
}
#grid-item-1 {
background: teal;
-ms-grid-column: 1;
-ms-grid-column-span: 2;
grid-column: span 2;
height: 150px;
transition: margin-left 500ms ease-in;
}
<button id="slide-btn">Slide</button>
<div id="grid">
<div id="grid-item-1"></div>
</div>
I have successfully created a CSS Grid layout. However, now I want to add support or a fallback for non or poorly supported browsers, specifically IE11.
I have added browser prefixes and read a million articles about adding floats, etc. I created a block of code that should work, but I cannot for the life of me get it to render when testing on IE11 (I have a Mac laptop with no access to a PC).
// sass-lint:disable no-important no-vendor-prefixes no-duplicate-properties final-newline
// Grid Variables
$cols: 12 !default;
$gutter: 50px !default;
// Breakpoints
$lg: 1199.98px;
$md: 991.98px;
$sm: 767.98px;
$xs: 575.98px;
$breakpoints: (
(l, $lg, 100%, 1),
(m, $md, 100%, 2),
(s, $sm, 100%, 2),
(x, $xs, 100%, 3),
(no, 0, 100%, 3)
) !default;
// Typography
$font-size: 20px;
$font-family: 'BrokenEn', serif;
$line-height: 1.4;
// Animations
$grid-animation: all .15s ease-in-out;
$grid-animation-slow: all .3s ease-in-out;
// Globals
*,
*::after,
*::before {
backface-visibility: hidden;
}
html {
box-sizing: border-box;
margin: 0;
overscroll-behavior: none;
padding: 0;
}
body {
background-color: #fff;
border: 0;
box-sizing: inherit;
color: #000;
font: normal 1rem $font-family;
height: 100%;
left: 0;
line-height: 1;
margin: 0;
overflow-x: hidden;
padding: 0;
position: relative;
}
// Grid
header,
main,
footer {
background-color: #f5f5dc;
width: 100%;
}
.r {
-ms-grid-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
background-color: #7fffd4;
display: -ms-grid !important;
display: grid !important;
grid-gap: $gutter;
grid-template-columns: repeat($cols, 1fr);
position: relative;
transition: $grid-animation;
}
[class*='c-'] {
-ms-grid-column-span: $cols;
background-color: #faebd7;
grid-column: span $cols;
position: relative;
&.nest {
-ms-grid-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
background-color: #7fffd4;
display: -ms-grid !important;
display: grid !important;
grid-gap: $gutter;
grid-template-columns: repeat($cols, 1fr);
position: relative;
}
&.contain-auto {
margin-left: $gutter;
margin-right: $gutter;
}
&.contain-fixed {
margin-left: auto;
margin-right: auto;
width: $lg;
}
}
.col-wrap {
display: inline-block;
padding: 0 $gutter;
width: 100%;
}
.no-c-gap {
grid-column-gap: 0 !important;
}
#for $i from 1 through $cols {
.c-#{$i} {
-ms-grid-column-span: $i;
grid-column: span $i;
}
}
#each $name, $size, $container, $divide in $breakpoints {
#media only screen and (max-width: $size) {
.r {
grid-gap: $gutter / $divide;
}
[class*='c-'] {
&.nest {
grid-gap: $gutter / $divide;
}
&.contain-auto {
margin-left: $gutter / $divide;
margin-right: $gutter / $divide;
}
}
#for $i from 1 through $cols {
.#{$name}#{$i} {
-ms-grid-column-span: $i;
grid-column: span $i;
}
}
}
}
#supports not (display: grid) {
.r {
display: inline-block !important;
width: 100% !important;
::after {
content: ' ';
display: block;
width: 100%;
}
[class*='c-'] {
display: block !important;
float: left !important;
margin: 0 $gutter $gutter 0;
}
}
#for $i from 1 through $cols {
.c-#{$i} {
width: calc((100% / #{$cols} * #{$i}) - #{$gutter}) !important;
}
}
#each $name, $size, $container, $divide in $breakpoints {
#media only screen and (max-width: $size) {
#for $i from 1 through $cols {
.#{$name}#{$i} {
width: calc((100% / #{$cols} * #{$i}) - #{$gutter}) !important;
}
}
}
}
}
// If #support not supported by browser.
#media all and (-ms-high-contrast: active), (-ms-high-contrast: none) {
.r {
display: inline-block !important;
width: 100% !important;
::after {
content: ' ';
display: block;
width: 100%;
}
[class*='c-'] {
display: block !important;
float: left !important;
margin: 0 $gutter $gutter 0;
}
}
#for $i from 1 through $cols {
.c-#{$i} {
width: calc((100% / #{$cols} * #{$i}) - #{$gutter}) !important;
}
}
#each $name, $size, $container, $divide in $breakpoints {
#media only screen and (max-width: $size) {
#for $i from 1 through $cols {
.#{$name}#{$i} {
width: calc((100% / #{$cols} * #{$i}) - #{$gutter}) !important;
}
}
}
}
}
Could someone help me look over the code and tell me how I can (1) better my grid, (2) get the "#supports not (display: grid)" code to work in IE11?
EDIT:
This would be an example of how it looks in all modern browsers, and how I would want it to look after the IE fallback kicks-in.
<body>
<header class="r">Header</header>
<main class="r">
<section class="c-12 nest ratio-4-3">
<div class="c-6">
<div class="wrap">Div Left</div>
</div>
<div class="c-6">
<div class="wrap">Div Left</div>
</div>
</section>
<section class="c-12 nest no-c-gap ratio-4-3">
<div class="c-6">
<div class="wrap">Div Left</div>
</div>
<div class="c-6">
<div class="wrap">Div Left</div>
</div>
</section>
</main>
<footer class="r">Footer</footer>
</body>
#supports isn't supported in IE So you have to put code in there for browsers that DO support grid. It should override your NON-Grid code. (remove the "not").
Grid is only partly supported in IE so you're likely better off using a polyfill for support over the partial options in the browser.
If you need to do a lot of cross-browser testing, look into a tool like BrowserStack.
Edit: to suggest a course of action.
I suggest this approach.
Re-write everything using a layout technique other than CSS Grid. People have been making cross-browser, performant, responsive layouts for years without grid. This will likely work across ALL your target browsers. If at this point, you get something better by using CSS Grid, use it as progressive enhancement.
The reason, I suggest this is a different layout technique might require additional containers/wrappers forcing your markup to change. It will be difficult to add these in, only "when grid won't work".
I'm using a feature query, my goal is to display grid on all browsers except IE. IE doesn't support feature queries, so all code in the feature query will be ignored.
It's working for me in IE, but on Chrome/all other browsers the code outside of the feature query is applying styles, but the feature query is still working like it's displaying grid, but also taking the margin/padding from the code outside of the feature query. Is there a way around this?
feature query
#supports(grid-auto-rows:auto){
.Gallery{
display:-ms-grid;
display:grid;
grid-gap: 5px;
grid-template-columns:repeat(auto-fit, minmax(170px, 1fr));
grid-auto-rows:95px;
grid-auto-flow: dense;
}
.horiz{
-ms-grid-column-span: 2;
grid-column: span 2;
}
.vert{
-ms-grid-row-span: 2;
grid-row: span 2;
}
.big{
-ms-grid-column-span:2;
grid-column:span 2;
-ms-grid-row-span: 2;
grid-row: span 2;
}
.imgContainer {
width: 100%;
height: 100%;
}
.img {
width: 100%;
height: 100%;
-o-object-fit: cover;
object-fit: cover;
}
}
styles outside of the feature query that's being applied
.Gallery {
display: flex;
flex-wrap: wrap;
margin: -1em 0 1em -0.5em;
}
.img {
padding: 1em 0 0 0.5em;
flex: 1 0;
min-width:100%;
height:100%;
}