Susy: fluid layout up to the second breakpoint - susy-compass

If I understand correctly, Susy's $container-style variable is a global setting. This means that if you use the following code, both layouts will be fluid.
$total-columns: 4;
$total-columns-large: 8;
$container-style: fluid;
#page {
#include container($total-columns, $total-columns-large);
}
But what if I want the 4-column layout to be fluid up to the (static) 8-column layout? I can think of a couple of ways to do that (like using at-breakpoint or with-grid-settings) but I'm curious if there is a better and/or recommended method.

Related

Disable style isolation in lit-element

Is it possible to apply framework styles to nested lit-element? An idea is to disable shadow dom. I tried this.
createRenderRoot() {
return this;
}
It does not do what I need. I see that I can recompile styles into components. But right now I am looking for an easier solution.
There is a solution - Specify the render root. This solution rid of shadowRoot. Styles were applied but , does not work.
If you want to use global styles you'll have to disable Shadow DOM in the whole app tree: if a single component has a shadow root its whole subtree won't be affected by external styles.
Anyway, as you noticed, slots only work with shadow DOM enabled. In this case using a common style library/framework is still possible, see for example Sharing Styles, Using Bootstrap in Web Components, Importing external stylesheets.
Yes, but disabling shadow DOM is the wrong way to do it it.
LitElement used adopted stylesheets, which let you load/create the CSS once, but apply it to the shadow DOM of the component. You can create this globally, apply it in each component, and effectivly have styles that are shared by all your components, but (critically) don't apply to any external component you load or any external app that loads your component.
You can do something like:
// common-styles.js
export const styles = css`...`;
// any-component.js
import { styles } from 'common-styles.js';
...
static get styles () { return [styles]; }
As the styles object is shared it doesn't download or parse again - all your components get a reference to the same styles, rather than global styles cascading down.
It works as designed. The version above does not use ShadowDom. So styles are applied. In my case, all components while style bubbling has to disable ShadowDom.
But another issue appears.
createRenderRoot() {
/**
* Render template without shadow DOM. Note that shadow DOM features like
* encapsulated CSS and slots are unavailable.
*/
return this;
}
But I need slots.
It depends on what properties you want to share.
You can share these properties from the parent element:
color
font-family and other font-* properties
All CSS custom properties (--*)
Just you need to define these properties in the parent element's :root selector.
For more information: https://lit.dev/docs/components/styles/#inheritance

Custom Header Layout - Spartacus Storefront

Has anyone solved or knows how to solve the following situation given the implementation of the header in Spartacus?
I would like to show in the header, a layout on the right of two level blocks, and on the left of a single level block.
Objective Header Layout
I can't think of how to do it since I can't see how to wrap certain slots, given the Spartacus implementation for the header.
Given the implementation of the header in Spartacus, inside the StorefrontComponent I cannot replace it using the ConfigModule.withConfig ({...}, as CmsConfig)
I understand and already tried that I can replace the header, implementing an Outlet (cxOutletRef = "header"), but this makes it impossible to edit it through SmartEdit, which is not acceptable to me.
Any suggestion? Or possible solution?
As a last option it occurs to me that I can create a component type from the back, and map it from Angular using "ConfigModule.withConfig ({...}, as CmsConfig)" implementing the "conflicting two-level" block from scratch or even the entire header.
Thank you !
////// CORRECTION 09/23/20 //////
Outlets do not prevent editing via SmartEdit. It's necessary to indicate the Slot to which the component corresponds, this is easy to implement using the PageSlotComponent.
✔ Example:
<ng-template cxOutletRef="cx-header">
<header
cxSkipLink="cx-header"
[cxFocus]="{ disableMouseFocus: true }"
[class.is-expanded]="isExpanded$ | async"
(keydown.escape)="collapseMenu()"
(click)="collapseMenuIfClickOutside($event)"
>
<cx-page-slot position="MiniCart"></cx-page-slot>
</header>
<cx-page-slot position="BottomHeaderSlot"> </cx-page-slot>
<cx-global-message></cx-global-message>
</ng-template>
In this way, SmartEdit does allow you to edit the MiniCart component, within its corresponding slot.
🚫 Wrong way:
<ng-template cxOutletRef="cx-header">
<header
cxSkipLink="cx-header"
[cxFocus]="{ disableMouseFocus: true }"
[class.is-expanded]="isExpanded$ | async"
(keydown.escape)="collapseMenu()"
(click)="collapseMenuIfClickOutside($event)"
>
<cx-mini-cart></cx-mini-cart>
</header>
<cx-page-slot position="BottomHeaderSlot"> </cx-page-slot>
<cx-global-message></cx-global-message>
</ng-template>
you can indeed solve this with a custom layout configuration and additional CSS, but it's not necessary. I give you a few options to consider:
Option 1: Change the generated DOM
You can either provide a custom layout config as #pwavg suggests, or even introducing a custom storefront component.
If you introduce a custom layout config, you're limited by the sections we use in the storefront component. If you insist on custom sections (ie. an element that wraps the searchbox, login, mincart and nav), you need to introduce a custom storefront component. The disadvantage here is that you'll deviating away from standard Spartacus component, which might result in missing features in the future.
Option 2: Pure CSS
A pure CSS solution is the easiest. You do not need to change any actual DOM, but apply some custom CSS rules to the standard DOM. Grid system is indeed designed for this. It's a bit complex to start with, but would do the job.
You can actually achieve this with flexbox as well, but you'd need to move the logo slot out of the flexbox flow.
Here's an actual quick and dirty code snippet to demonstrate changing by a few CSS rules only. It comes with a few assumptions/limitations, but for most cases it might be fine.
header {
cx-page-slot.SiteLogo {
// we absolute position the logo, so it flows outside the flexbox system. this requires
// an hard-coded top position, that might be fine, but I don't know the details.
position: absolute;
top: 60px;
}
cx-page-slot.SearchBox {
// align searchbox to the left, not sure if that's required, but looks better
margin: 14px auto 14px 150px;
}
cx-page-slot.NavigationBar {
margin-left: 150px;
overflow: hidden;
}
// manipulate a very high logo to demonstrate this works
cx-page-slot.SiteLogo img {
height: 100px;
}
}
Result (sorry for the logo ;) )
Option 3: cx-header Outlet
I would say you should be able to use outlets as well, as this will get you closer to option 1 (changing the actual DOM). I can't think of a reason why it would not work in SmartEdit - but happy to learn if it is the case. I'd recommend in this case to use the cx-header outletRef, so you would replace the entire header.
I am not super experienced with Spartacus so this might not be the correct way. Just trying to think with you on this.
I think you can just extend you layoutconfig and style the slots with CSSGrid. So for example you layout could be something like this:
layoutSlots: {
header: {
lg: {
slots: [
'SiteLinks',
'SiteLogin',
'HeaderLinks',
'SiteLogo',
'NavigationBar',
'SearchBox',
'MiniCart',
'NavigationBar2',
],
},
slots: ... (for mobile view)
},
},
And create a custom css grid for the positions of the slot.
If you want to have more markup control you could use cxOutletRef to replace the header with something like:
<ng-template cxOutletRef="cx-header">
<header>
<div class="header-top">
<cx-page-layout section="headerTop"></cx-page-layout>
</div>
<div class="header-bottom">
<cx-page-layout section="headerBottom"></cx-page-layout>
</div>
</header>
</ng-template>
And then divide the slots between headerTop and headerBottom in you config.

How to span a number of columns, regardless of the nested grid context?

I need to set the width of an element that is used in various places in my fluid Susy layout. The parent element is not always the same width, but I want this element to always have the same width relative to the page width.
Example:
In a 12-column grid, a news article sometimes spans 12 columns, sometimes 6. Editors are able to add a <blockquote> in the news article text. I want a blockquote to always be 3 columns wide (relative to the full page), regardless of its context (12 or 6 columns).
Of course if this was a grid with fixed column widths it would be easier, but I'm looking for a fluid, percentage-based solution.
PS. I am willing to use Susy 2 alpha if that makes it easier to solve the problem.
You would do this the same way in Susy 1 or 2, though it's always more fun in 2. :)
The issue isn't really related to anything specific about Susy, it would be a problem in any fluid CSS situation. You can only solve it if you have a hook for knowing which context you are in. At that point, you can solve it from either end. Something like this:
blockquote {
#include span-columns(3);
.narrow & { #include span-columns(3,6); }
}
There really isn't any way to do it without the hook. CSS doesn't have element-queries (and isn't likely to any time soon, for the reasons given in that article).

JavaFX TableView: Cannot Override '-fx-text-fill'!

On JavaFX2.2, I created my own style class to represent table cells that contain invalid data. But my style class seems unable to override -fx-text-fill in the hover, selected, and focused states. Here is my style class:
.invalid-table-cell {
-fx-text-fill: red;
}
.invalid-table-cell:hover {
-fx-background-color: salmon;
-fx-text-fill: blue; /* No worky */
}
.invalid-table-cell:selected {
-fx-background-color: purple;
-fx-text-fill: orchid; /* No worky */
}
.invalid-table-cell:focused:hover {
-fx-background-color: red;
-fx-text-fill: green; /* No worky */
}
When my app runs, I can see changes in -fx-background-color, but I see no changes in -fx-text-fill in any of the special states.
What am I doing wrong?
!important is likely required due to the specificity of your css rules versus the css rules of the default caspian or modena stylesheets (though my css skills are limited in terms of evaluating this).
SceneBuilder 1.1 has a css analyzer that can help determine what css rules and attributes are being activated. That may help in debugging css rule activation in general, though it is not much help in this specific case unfortunately as you can't set the styles on table cells through SceneBuilder 1.1.
One work-around is to copy all of the table-view css rules from the modena or caspian css (unfortunately there is a lot of them) and place the rules in your user stylesheet. Prepend the style selection element .invalid-table-cell to each of the table css rules in your user stylesheet and modify the rules as appropriate to achieve your desired look and feel. This will ensure that your ruleset has the correct level of specificity to override the default rules. It is unfortunately, a pretty arduous process and perhaps your !important overrides might be a better solution for you.
A slightly easier way to customize styles is to override predefined constants, for example something like below (which I haven't tried and just demonstrates a principle as the exact selector and rules needed may differ):
.invalid-table-cell {
-fx-selection-bar-text: goldenrod;
}
As much of the default table cell styles are defined using -fx-text-fill: -fx-selection-bar-text;, just setting this value to the appropriate value allows you to override all of those default table cell styles. But it overrides them all to the same value, so if you need different values for different css psuedo-states like in your question, then you will need to define those rules explicitly as outlined earlier.
Following jewelsea's advice, I increased the specificity of my CSS rules to match the specificity of the corresponding rules in capsian.css. Because I was curious, I increased the specificity of my own rules incrementally and discovered that anything less specific than the following rules does not work in my situation.
.table-view:cell-selection .table-row-cell:filled .invalid-table-cell:hover {
/* Works! */
}
.table-view:focused .table-row-cell:filled .invalid-table-cell:selected:focused {
/* Works! */
}
.table-view:focused .table-row-cell:filled .invalid-table-cell:focused:selected:hover {
/* Works! */
}

Combining Susy at-breakpoint() and device orientation media queries

I'm relatively new to Susy and responsive design. I've managed to setup my grid and using at-breakpoint(), I've made the page fully responsive as required first by testing it while resizing the browser window, and then testing it on the actual mobile devices (phones and tablets). I encounter a problem with the iPad as requires an extra orientation rule (orientation: landscape) in the media query. What's the workaround here, is there a way to include it in the at-breakpoint rule or I'll have to make up a separate media query just for this case?
Here's my grid setup:
$total-columns: 4;
$column-width: 60px;
$gutter-width: 20px;
$grid-padding: $gutter-width/2;
// alternative layout breakpoints
$tablet-small: 6;
$tablet: 8;
$computer: 12;
And when dealing with the sidebar and the page body, first I display them as block elements to fill the entire page horizontally, and after the breakpoint I make them behalf as columns like so:
#sidebar {
#include at-breakpoint($computer) {
#include span-columns(3, $computer);
}
} // sidebar
#page-body {
#include at-breakpoint($computer) {
#include span-columns(9 omega, $computer);
}
} // page-body
How should I alter the code so that it keeps the variables for the breakpoints and just add the orientation rule? Thanks!
If you want to target specific device, I think it's better to specify the width.
So instead of $computer: 12; maybe do $computer: 48em 12;
Once the min-width: 48em; is reached, it will change the layout to become a 12 column grid.
something like this SHOULD work:
$device-lrg-landscape: max-device-width 480px, orientation landscape
#include breakpoint($device-lrg-landscape)

Resources