Styling Layout Wrappers In CSS
Strategy

Styling Layout Wrappers In CSS


A website content should be wrapped or contained in a width that makes the content easy to read. To achieve that, we can use what has been called a wrapper, or a container. Using a wrapper in CSS can be possible in different ways which might introduce some challenges along with it.

In this article, I will explain about layout wrappers in CSS, how they work, how to use them, and when not to use them. Notice that throughout this article, I might mention the terms wrapper and container, and both of them means the same.

Are you ready? Let’s dive in!

A brief about wrappers

When you hear the word wrapper or container, it’s actually means that a group of elements is wrapped or contained inside another element. Without using additional elements, we can add a wrapper to the <body> element as below:

body {
    max-width: 1170px;
    margin-left: auto;
    margin-right: auto;
    padding-left: 16px;
    padding-right: 16px;
}

However, adding the wrapper to the <body> element might not practical for today’s work. The wrapper element can prevent child items from going outside its boundaries. Consider the following figure:

We have aside and main elements, and they live inside another element that wraps them. The .wrapper element has a width, of course.

<div class="wrapper">
    <aside>...</aside>
    <main>...</main>
</div>

Without a wrapper, the child elements will stick to the edges of the screen. This can be very annoying to the user, especially on a large screen.

The figure above shows how the elements will stretch when there is no element wrapping them. This behavior isn’t something that a user should experience. Let me explain the reason behind that.

Why page wrappers are necessary

Using a page wrapper can have many benefits that you should be aware of them as a designer or a developer. Here are some of the benefits:

  1. Making the content more readable. Without a wrapper, content like text and images can stretch to fill the whole width of the screen. For small screens, this might seems ok. However, for a large screen, this is extremely annoying.
  2. Grouping design elements are better for adding spacing.
  3. Dividing design elements into columns can’t be done easily without a wrapper.

Implementing a wrapper in CSS

Now that you understand the basics and the benefits of a wrapper, let’s explore how to build one in CSS.

Adding the width

The first thing to decide about when implementing a wrapper is the width of it. How do you want the wrapper width to be? That depends on your design. Generally speaking, having a wrapper width that ranges between 1000px - 1300px is the most commonly used. The popular framework Bootstrap, for example, uses a width of 1170px.

.wrapper {
    width: 1170px;
}

However, it’s not recommended to use the width property as it will cause horizontal scrolling when the screen size is less than 1170px. You can solve it by adding max-width, though.

.wrapper {
    width: 1170px;
    max-width: 100%;
}

While this works, you can get rid of width and use the max-width only as the following.

.wrapper {
    max-width: 1170px;
}

Now that we added the width for the wrapper. Let’s move on to centering it.

Centering the wrapper

To center the wrapper, you should add an auto margin from the left and right sides. See the following:

.wrapper {
    max-width: 1170px;
    margin: 0 auto;
}

According to the CSS spec, here is how auto margins work:

If both ‘margin-left’ and ‘margin-right’ are ‘auto’, their used values are equal. This horizontally centers the element with respect to the edges of the containing block.

If you are interested to dig in the auto keyword, I wrote a detailed article about it.

I used margin: 0 auto, this basically reset the margin for the top and bottom to zero and make it auto for the left and right sides. There are some consequences of using this, but I will come to them later in this article. For now, it’s recommended to use the longhand version of the margins.

.wrapper {
    max-width: 1170px;
    margin-left: auto;
    margin-right: auto;
}

Add padding on the left and right sides

An important thing to consider is to add padding for the left and right sides. When the viewport size is less than the maximum width of the wrapper, this will cause the wrapper edges to stick to the viewport.

.wrapper {
    max-width: 1170px;
    margin-left: auto;
    margin-right: auto;
    padding-left: 16px;
    padding-right: 16px;
}

By adding the padding, we can make sure that we will have a 16px offset from the left and right sides, even if the viewport size is less than the maximum width. The padding acts as a protective strategy that avoids making the wrapper sticking to the viewport edges when space is not enough.

22 June update: Using a percentage width for the wrapper

I got a reply about using a percentage width like max-width: 90% for the wrapper instead of using padding-left and padding-right.

While this works, the 90% of the viewport width will be too much on large screens, which you can override with a media query.

.wrapper {
    max-width: 90%;
    margin-left: auto;
    margin-right: auto;
}

/* A media query for a large screen */
@media (min-width: 1170px) {
    .wrapper {
        max-width: 1170px;
    }
}

By using a percentage width, we added an extra step. We can avoid this step easily by using a fixed width value. Another solution suggested in this tweet says that we can combine width: 90% with a max-width: 1170px property.

.wrapper {
	width: 90%;
	max-width: 1170px;
	margin-left: auto;
	margin-right: auto;
}

That’s an interesting approach, but I would prefer to add the padding myself instead of depending on the percentage width.

The display type of a wrapper

Since the wrapper is a <div>, it’s a block-level element by default. The question is, what should we do if we want to change the display type to grid, when the content inside the wrapper should be placed in a grid?

Well, I don’t recommend doing that as it stands against the concept of separation of concerns. A wrapper is for wrapping other contents, that’s all. If you need a grid wrapper, then adding another <div> inside the wrapper with display: grid is easier, clear, and more maintainable in the future.

<div class="wrapper">
    <!-- Content -->
</div>

This is not recommended, the wrapper element could be used on another page and this might break the layout unintentionally.

.wrapper {
    display: grid;
    grid-template-columns: 2fr 1fr;
    grid-gap: 16px;
}

A better solution would be as the following:

<div class="wrapper">
    <div class="featured-news">
        <!-- Elements that needs to be placed in a grid -->
    </div>
</div>
.featured-news {
    display: grid;
    grid-template-columns: 2fr 1fr;
    grid-gap: 16px;
}

Notice how I added a separated <div> element to wrap the content. Please don’t mind the class and naming conventions for this example. We can have an even better solution by using a class naming that can be reused across different pages on the website. However, CSS naming conventions are out the scope of this article.

Adding margin between wrappers

Do you remember when I didn’t recommend using the shorthand version to center the wrapper element? I mean this:

.wrapper { 
    margin: 0 auto;
}

While it works, it can get confusing when you have multiple wrappers on the page and you need to add spacing between them. If for some reason you added another variation class to the .wrapper, adding the margin might not work for specificity reasons.

.wrapper-variation {
    margin-top: 50px;
}

.wrapper { 
    max-width: 1170px;
    margin-left: auto;
    margin-right: auto;
    padding-left: 16px;
    padding-right: 16px;
}

The margin for the .wrapper-variation element won’t work because it’s overridden by margin: 0 auto. A shorthand property overrides a longhand one. To avoid such confusion, it’s recommended to use longhand for such cases.

Now let’s get to adding the margin. In each project, I prepare a set of utility classes for margin and padding, and I use them when necessary. Consider the following figure.

<div class="wrapper mb-5"></div>
<section>
    <div class="wrapper"></div>
</section>
<div class="wrapper"></div>
.mb-5 {
    margin-bottom: 3rem !important;
}

That way, the wrapper CSS stays as it is, and the spacing is added with an additional CSS utility class. Now, you might ask, why do I need to add multiple wrappers to a page, when I can add one? In the HTML above, there is a <section> element between two wrappers.

Using !important here is good, as the point of utility classes is to force a property, and by adding !important, we can ensure that.

A wrapper inside a full-screen section

There might be cases when you have a section with a background that has 100% viewport width, and within it, there is a wrapper. It’s similar to what is introduced in the previous example.

A page HTML structure can be like that:

<section>
    <div class="wrapper"></div>
</section>
<section>
    <div class="wrapper"></div>
</section>

The <section> has 100% width of the viewport. You can add a background color or image to it. Inside it, the wrapper prevents the content from becoming taking the full width of the viewport.

In the figure above, the section has a background image and it’s taking the full width of the viewport. The content inside is restricted by the wrapper’s width.

Does a hero section need a wrapper?

Well, it depends. Let’s explore the two most commonly used hero section designs.

The first one has its content centered and is constrained by a specific width.

The second one has its content spread to the main wrapper width.

To understand the two patterns better, let’s explore how to build each one of them.

A Hero with centered content

You might be tempted to place the hero content and then center everything without considering the wrapper.

<section class="hero">
    <h2>How to make bread at home</h2>
    <p>....</p>
    <p><a href="/sign-up">Sign up</a></p>
</section>

With the HTML above, you could center the content with text-align:

.hero { text-align: center; }

This will look good until you resize the browser window. Here are the issues you might notice.

The content is stick to the edges.

Since there is no padding on the left and right sides, the content will stick to the edges without proper spacing. This is bad for the user as it will make it harder to observe and read the content.

Long line length for large screens

On large screens, the paragraph text can be very hard to read since the line length is too long. As per The Elements of Typographic Style Applied to the Web, the recommended number of characters for a line is 45 to 75. Anything far from that range will make the reading harder.

To avoid the above issues, a wrapper can be used to prevent the text length from becoming too long and to add spacing in mobile.

<section class="hero">
    <div class="hero__wrapper">
            <h2>How to make bread at home</h2>
            <p>...</p>
            <p><a href="/sign-up">Sign up</a></p>
    </div>
</section>

I used the class hero__wrapper since this wrapper might be custom only for the hero section, so it can have a certain width which is smaller than the usual wrapper element.

.hero__wrapper {
    max-width: 720px;
    margin-left: auto;
    margin-right: auto;
    padding-left: 16px;
    padding-right: 16px;
}

For centering the content, it can be done using the technique of your choice, depending on the use-case. For this example, using text-align: center is enough to center the content.

Should the wrapper be centered or left-aligned?

I don’t know if there is a black or white for this question, but I’ve seen websites that center the wrapper on laptop screens, and it’s left-aligned on desktop sizes.

The Techcrunch website is an example of this. Notice how the website is left-aligned on large screens.

For me, I love reading a website that is centered and has symmetrical spacing on the left and right sides. But it could be a reason that I don’t know about it. If you have an idea, please let me know on Twitter!

Using CSS variables for wrapper variations

It’s rare that you only need a wrapper with one size. A wrapper width could be small or big, depending on the content and use-case. By leveraging CSS variables, we can create a modern take on a wrapper, and you will have great flexibility. Consider the below:

<div class="wrapper"></div>
.wrapper {
    max-width: var(--wrapper-width, 1170px);
    margin-left: auto;
    margin-right: auto;
    padding-left: 16px;
    padding-right: 16px;
}

If you notice, the var has two values, the first one if the variable --wrapper-width, and the second one is 1170px. The second variable is a fallback, which means that if the variable --wrapper-width is not set, the second one will be used.

What does that mean? It means that you can create a variation of the wrapper, by overriding the --wrapper-width as below:

<div class="wrapper" style="--wrapper-width: 720px"></div>

That way, I created a custom wrapper without:

  • Adding a new class
  • Copying and duplicating styles
  • More future-proof and can be easily tweaked from the DevTools

If you don’t like the solution of adding an inline style for overriding the CSS variable, you can add a new class instead. See below:

<div class="wrapper wrapper--small"></div>
.wrapper--small {
    --wrapper-width: 720px;
    /* this will override the default wrapper width. */
}

Demo

Using CSS display: contents

First, let me brief you about this value. Each element in CSS is a box, and that box contains content, padding, margin, and border. By using display: contents, that box will be removed from the flow. I can imagine it as removing the surrounding opening and closing tags.

<header class="site-header">
    <div class="wrapper site-header__wrapper">
            <!-- Header content -->
    </div>
</header>
.site-header__wrapper {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
}

In the example above, you might need to let the header expand to the full width of the page, instead of being restricted by the wrapper width.

.site-header__wrapper {
    display: contents;
}

.site-header {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
}

By doing that, the .wrapper element will be hidden (kind of). Now, when display: flex is applied to the .site-header element, the descendants items of the .wrapper will be the child items of .site-header.

Fluid background, fixed content

In her CSS Secrets book, Lea Verou introduced an interesting technique that can be used for sections that have a fluid background (taking the full viewport width) with a wrapper inside it. Let’s review the common way of doing it.

<section>
	<div class="wrapper"></div>
</section>
section {
	background-color: #ccc;
}

.wrapper {
	max-width: 1170px;
	margin-left: auto;
	margin-right: auto;
	padding-left: 16px;
	padding-right: 16px;
}

The margin-left: auto and margin-right: auto works in a way that computes half the viewport width, minus the content width. That same thing can be done using padding.

section {
  padding: 1rem calc(50% - 585px);
}

We are not done yet. The content will be sticked to the edges on mobile. A solution for that would be the following.

section {
  padding: 1rem;
}

@media (min-width: 1170px) {
	section {
	  padding: 1rem calc(50% - 585px);
	}
}

An alternative solution would be to use the new CSS max() function. Simply, we set a minimum padding of 1rem, and the 50% - 585px calculation can be used as the other value.

section {
  padding: 1rem max(1rem, (50% - 585px));
}

If you want to learn more about min(), max(), and clamp(), I wrote a detailed article about them.

The End

That’s a wrap. Do you have a comment or a suggestion? Please feel free to ping me on @shadeed9.

Thank you for reading.





Source link

Flexbox diagram
Strategy

How to Add Responsive Design to React Native Apps


Native application developers put a lot of effort into making engaging and stable apps that are supported on multiple devices. This means that Android developers have to make sure that their apps are supported on hundreds of devices. iOS developers also need to support their apps on a growing number of devices.  

React Native enables developers to develop apps that can run both on iOS and Android. The problem is that the number of devices they need to support now is doubled. One particular problem is making the app responsive. There is no such thing as CSS media queries in React Native. React Native developers need to scale all of their layouts to make the app responsive on smartphones, tablets, and other devices.

Problems With Responsive Layout in React Native

React Native developers make their apps work on one-dimensional devices as a default. As a result, the app looks distorted on devices with different dimensions because different devices have different pixel ratios. React Native style properties accept either Density-Independent Pixels (DP) or percentage.

Independent Pixels

A density-independent pixel is a unit of length that enables mobile apps to scale across different screen sizes. DPs are not the classic screen pixels. Rather, DPs are mathematically calculated through the following equation: DP=PX/ScaleFactor.

PX is the number of classic screen pixels, and the scaling factor indicates how much the pixels should be enlarged.

React Native developers can scale DP values to screens of different sizes only if they have the same resolution. The problem is that there are hundreds of different devices and most of them have screens with different resolutions.

Percentage

Most web development frameworks use percentage values to design different layouts. However, React Native style properties like border-radius and border-width do not accept percentage value. Properties that do accept percentage include maxWidth, minWidth, margin and height.

5 Tips for Creating Responsive Layouts for React Native Apps

The following tips will help you develop responsive React Native apps on a massive range of devices.

1. Layout With Flexbox

Flexbox is a method for laying out one-dimensional items in rows or columns. Flexbox enables developers to keep layout proportions on different screen sizes. Flexbox properties use single numbers to divide the screen space between elements. For example, a screen that shows boxes of different colors, as shown in the image below.

Flexbox diagram

Image Source

The red box is defined as flex: 1, the yellow box is flex: 2, the green box is flex: 3. This means that the red box gets 1/6 of the screen, the yellow gets 2/6, and the green gets 3/6. 

Main Flexbox properties include:

  • Flex direction—controls the direction or the main axis of the content layout. You can layout the content in a row or in a column. The default direction is a column because of the nature of mobile device screens.

  • Justify content—describes the position of content along the main axis. You can align the content to the right-left of the center of the main axis. You can also determine the space between content components.

  • Align items—aligns content on the cross axis, as opposed to justifyContent that aligns on the main axis.

2. Aspect Ratio

Aspect ratio describes the relationship between the width and the height of an image. Aspect ratio is usually expressed as two numbers separated by a colon, like 16:9. Aspect ratio is a non-standard property available only in React Native, and not in CSS. The aspect ratio property controls the size of undefined element dimensions. 

For example, you can use the aspectRatio property to adjust images to screen size when your images extend beyond the screen dimensions. You do not need to know the actual width and height of the image, just set the aspect ratio to 1:1. Your images will take all available screen width, without extending beyond the dimensions.

3. Screen Dimensions

React Native does not provide properties that can identify the device type or screen size when you work with different layouts. The solution is to use the Dimensions API. The syntax for obtaining the dimensions of a screen is:

After obtaining the size of the screen, you can set breakpoints for layout changes. You can also define different styles to components or hide some parts of the screen.

4. Detect the Platform

The platform module in React Native detects if the app is running on Android or iOS. Developers can use this module to implement platform-specific code. For example, the code below will show the text “My device is Apple” when the app runs on iOS. 

The platform module is also useful when you want to define the size of an image for specific devices. For example, the code below defines the height of an image for iOS devices.

5. Device Screen Orientation

Many apps can work in landscape and portrait mode. Sometimes, the layout can change drastically when you flip the device. Therefore, you have to ensure that the layout does not break when changing orientation. 

The React Native Dimensions library can dynamically detect device screen orientation changes. The library provides an addEventListener method that is triggered when the screen orientation changes.

Conclusion

This article reviewed responsive layouts challenges in React Native apps and provided solutions for making your responsive layouts much easier. Responsiveness solutions include techniques like Flexbox, dimensions, and aspect ratio properties. In addition, you can detect the device platform and screen orientation to adjust your app to different screen sizes. 



Source link

Screenshot. Shows the `Incompatible units:
Strategy

When Sass and New CSS Features Collide


Recently, CSS has added a lot of new cool features such as custom properties and new functions. While these things can make our lives a lot easier, they can also end up interacting with preprocessors, like Sass, in funny ways.

So this is going to be a post about the issues I’ve encountered, how I go around them, and why I still find Sass necessary these days.

The errors

If you’ve played with the new min() and max() functions, you may have ran into an error message like this when working with different units: “Incompatible units: vh and em.”

Screenshot. Shows the `Incompatible units: 'em' and 'vh'` error when trying to set `width: min(20em, 50vh)`.
An error when working with different types of units in the min()/ max() function

This is because Sass has its ownmin() function, and ignores the CSS min() function. Plus, Sass cannot perform any sort of computation using two values with units that don’t have a fixed relation between them.

For example, cm and in units have a fixed relation between them, so Sass can figure out what’s the result of min(20in, 50cm) and doesn’t throw an error when we try to use it in our code.

The same things goes for other units. Angular units, for example, all have a fixed relation between them: 1turn, 1rad or 1grad always compute to the same deg values. Same goes for 1s which is always 1000ms, 1kHz which is always 1000Hz, 1dppx which is always 96dpi, and 1in which is always 96px. This is why Sass can convert between them and mix them in computations and inside functions such as its own min() function.

But things break when these units don’t have a fixed relation between them (like the earlier case with em and vh units).

And it’s not just different units. Trying to use calc() inside min() also results in an error. If I try something like calc(20em + 7px), the error I get is, “calc(20em + 7px) is not a number for min.”

Screenshot. Shows the `'calc(20em + 7px)' is not a number for 'min'` error when trying to set `width: min(calc(20em + 7px), 50vh)`.
An error when using different unit values with calc() nested in the min()function

Another problem arises when we want to use a CSS variable or the result of a mathematical CSS function (such as calc(), min() or max()) in a CSS filter like invert().

In this case, we get told that “$color: 'var(--p, 0.85) is not a color for invert.”

Screenshot. Shows the `$color: 'var(--p, 0.85)' is not a color for 'invert'` error when trying to set `filter: invert(var(--p, .85))`.
var() in filter: invert() error

The same thing happens for grayscale(): “$color: ‘calc(.2 + var(--d, .3))‘ is not a color for grayscale.”

Screenshot. Shows the `$color: 'calc(.2 + var(--d, .3))' is not a color for 'grayscale'` error when trying to set `filter: grayscale(calc(.2 + var(--d, .3)))`.
calc() in filter: grayscale() error

opacity() causes the same issue: “$color: ‘var(--p, 0.8)‘ is not a color for opacity.”

Screenshot. Shows the `$color: 'var(--p, 0.8)' is not a color for 'opacity'` error when trying to set `filter: opacity(var(--p, 0.8))`.
var() in filter: opacity() error

However, other filter functions — including sepia(), blur(), drop-shadow(), brightness(), contrast() and hue-rotate()— all work just fine with CSS variables!

Turns out that what’s happening is similar to the min() and max() problem. Sass doesn’t have built-in sepia(), blur(), drop-shadow(), brightness(), contrast(), hue-rotate() functions, but it does have its own grayscale(), invert() and opacity() functions, and their first argument is a $color value. Since it doesn’t find that argument, it throws an error.

For the same reason, we also run into trouble when trying to use a CSS variable that lists at least two hsl()or hsla() values.

Screenshot. Shows the `wrong number of arguments (2 for 3) for 'hsl'` error when trying to set `color: hsl(9, var(--sl, 95%, 65%))`.
var() in color: hsl() error.

On the flip side, color: hsl(9, var(--sl, 95%, 65%)) is perfectly valid CSS and works just fine without Sass.

The exact same thing happens with the rgb()and rgba() functions.

Screenshot. Shows the `$color: 'var(--rgb, 128, 64, 64)' is not a color for 'rgba'` error when trying to set `color: rgba(var(--rgb, 128, 64, 64), .7)`.
var() in color: rgba() error.

Furthermore, if we import Compass and try to use a CSS variable inside a linear-gradient() or inside a radial-gradient(), we get another error, even though using variables inside conic-gradient() works just fine (that is, if the browser supports it).

Screenshot. Shows the At least two color stops are required for a linear-gradient error when trying to set background: linear-gradient(var(--c, pink), gold).
var() in background: linear-gradient() error.

This is because Compass comes with linear-gradient() and radial-gradient() functions, but has never added a conic-gradient() one.

The problems in all of these cases arise from Sass or Compass having identically-named functions and assuming those are what we intended to use in our code.

Drat!

The solution

The trick here is to remember that Sass is case-sensitive, but CSS isn’t.

That means we can write Min(20em, 50vh)and Sass won’t recognize it as its own min() function. No errors will be thrown and it’s still valid CSS that works as intended. Similarly, writing HSL()/ HSLA()/ RGB()/ RGBA() or Invert() allows us to avoid issues we looked at earlier.

As for gradients, I usually prefer linear-Gradient() and radial-Gradient() just because it’s closer to the SVG version, but using at least one capital letter in there works just fine.

But why?

Almost every time I tweet anything Sass-related, I get lectured on how it shouldn’t be used now that we have CSS variables. I thought I’d address that and explain why I disagree.

First, while I find CSS variables immensely useful and have used them for almost everything for the past three years, it’s good to keep in mind that they come with a performance cost and that tracing where something went wrong in a maze of calc() computations can be a pain with our current DevTools. I try not to overuse them to avoid getting into a territory where the downsides of using them outweigh the benefits.

Screenshot. Shows how `calc()` expressions are presented in DevTools.
Not exactly easy to figure out what’s the result of those calc() expressions.

In general, if it acts like a constant, doesn’t change element-to-element or state-to-state (in which case custom properties are definitely the way to go) or reduce the amount of compiled CSS (solving the repetition problem created by prefixes), then I’m going to use a Sass variable.

Secondly, variables have always been a pretty small portion of why I use Sass. When I started using Sass in late 2012, it was primarily for looping, a feature we still don’t have in CSS. While I’ve moved some of that looping to an HTML preprocessor (because it reduces the generated code and avoids having to modify both the HTML and the CSS later), I still use Sass loops in plenty of cases, like generating lists of values, stop lists inside gradient functions, lists of points inside a polygon function, lists of transforms, and so on.

Here’s an example. I used to generate n HTML items with a preprocessor. The choice of preprocessor matters less, but I’ll be using Pug here.

- let n = 12;

while n--
  .item

Then I would set the $n variable into the Sass (and it would have to be equal to that in the HTML) and loop up to it to generate the transforms that would position each item:

$n: 12;
$ba: 360deg/$n;
$d: 2em;

.item {
  position: absolute;
  top: 50%; left: 50%;
  margin: -.5*$d;
  width: $d; height: $d;
  /* prettifying styles */

  @for $i from 0 to $n {
    &:nth-child(#{$i + 1}) {
      transform: rotate($i*$ba) translate(2*$d) rotate(-$i*$ba);
			
      &::before { content: '#{$i}' }
    }
  }
}

However, this meant that I would have to change both the Pug and the Sass when changing the number of items, making the generated code very repetitive.

Screenshot. Shows the generated CSS, really verbose, almost completely identical transform declaration repeated for each item.
CSS generated by the above code

I have since moved to making Pug generate the indices as custom properties and then use those in the transform declaration.

- let n = 12;

body(style=`--n: ${n}`)
  - for(let i = 0; i < n; i++)
    .item(style=`--i: ${i}`)
$d: 2em;

.item {
  position: absolute;
  top: 50%;
  left: 50%;
  margin: -.5*$d;
  width: $d;
  height: $d;
  /* prettifying styles */
  --az: calc(var(--i)*1turn/var(--n));
  transform: rotate(var(--az)) translate(2*$d) rotate(calc(-1*var(--az)));
  counter-reset: i var(--i);
	
  &::before { content: counter(i) }
}

This significantly reduces the generated code.

Screenshot. Shows the generated CSS, much more compact, no having almost the exact same declaration set on every element separately.
CSS generated by the above code

However, looping in Sass is still necessary if I want to generate something like a rainbow.

@function get-rainbow($n: 12, $sat: 90%, $lum: 65%) {
  $unit: 360/$n;
  $s-list: ();
	
  @for $i from 0 through $n {
    $s-list: $s-list, hsl($i*$unit, $sat, $lum)
  }
	
  @return $s-list
}

html { background: linear-gradient(90deg, get-rainbow()) }

Sure, I could generate it as a list variable from Pug, but doing so doesn’t take advantage of the dynamic nature of CSS variables and it doesn’t reduce the amount of code that gets served to the browser, so there’s no benefit coming out of it.

Another big part of my Sass (and Compass) use is tied to built-in mathematical functions (such as trigonometric functions), which are part of the CSS spec now, but not yet implemented in any browser. Sass doesn’t come with these functions either, but Compass does and this is why I often need to use Compass.

And, sure, I could write my own such functions in Sass. I did resort to this in the beginning, before Compass supported inverse trigonometric functions. I really needed them, so I wrote my own based on the Taylor series. But Compass provides these sorts of functions nowadays and they are better and more performant than mine.

Mathematical functions are extremely important for me as I’m a technician, not an artist. The values in my CSS usually result from mathematical computations. They’re not magic numbers or something used purely for aesthetics. A example is generating lists of clip paths points that create regular or quasi-regular polygons. Think about the case where we want to create things like non-rectangular avatars or stickers.

Let’s consider a regular polygon with vertices on a circle with a radius 50% of the square element we start from. Dragging the slider in the following demo allows us to see where the points are placed for different numbers of vertices:

Putting it into Sass code, we have:

@mixin reg-poly($n: 3) {
  $ba: 360deg/$n; // base angle
  $p: (); // point coords list, initially empty
	
  @for $i from 0 to $n {
    $ca: $i*$ba; // current angle
    $x: 50%*(1 + cos($ca)); // x coord of current point
    $y: 50%*(1 + sin($ca)); // y coord of current point
    $p: $p, $x $y // add current point coords to point coords list
  }
	
  clip-path: polygon($p) // set clip-path to list of points
}

Note that here we’re also making use of looping and of things such as conditionals and modulo that are a real pain when using CSS without Sass.

A slightly more evolved version of this might involve rotating the polygon by adding the same offset angle ($oa) to the angle of each vertex. This can be seen in the following demo. This example tosses in a star mixin that works in a similar manner, except we always have an even number of vertices and every odd-indexed vertex is situated on a circle of a smaller radius ($f*50%, where $f is sub-unitary):

We can also have chubby stars like this:

Or stickers with interesting border patterns. In this particular demo, each sticker is created with a single HTML element and the border pattern is created with clip-path, looping and mathematics in Sass. Quite a bit of it, in fact.

Another example are these card backgrounds where looping, the modulo operation and exponential functions work together to generate the dithering pixel background layers:

This demo just happens to rely heavily on CSS variables as well.

Then there’s using mixins to avoid writing the exact same declarations over and over when styling things like range inputs. Different browsers use different pseudo-elements to style the components of such a control, so for every component, we have to set the styles that control its look on multiple pseudos.

Sadly, as tempting as it may be to put this in our CSS:

input::-webkit-slider-runnable-track, 
input::-moz-range-track, 
input::-ms-track { /* common styles */ }

…we cannot do it because it doesn’t work! The entire rule set is dropped if even one of the selectors isn’t recognized. And since no browser recognises all three of the above, the styles don’t get applied in any browser.

We need to have something like this if we want our styles to be applied:

input::-webkit-slider-runnable-track { /* common styles */ }
input::-moz-range-track { /* common styles */ }
input::-ms-track { /* common styles */ }

But that can mean a lot of identical styles repeated three times. And if we want to change, say, the background of the track, we need to change it in the ::-webkit-slider-runnable-track styles, in the ::-moz-range-track styles and in the ::-ms-track styles.

The only sane solution we have is to use a mixin. The styles get repeated in the compiled code because they have to be repeated there, but we don’t have to write the same thing three times anymore.

@mixin track() { /* common styles */ }

input {
  &::-webkit-slider-runnable-track { @include track }
  &::-moz-range-track { @include track }
  &::-ms-track { @include track }
}

The bottom line is: yes, Sass is still very much necessary in 2020.



Source link

Create Progress Bar Using Ngx-Bootstrap In Angular 8
Strategy

Create Progress Bar Using Ngx-Bootstrap In Angular 8


Introduction

In this article, we are going to learn how to create a progress bar using ngx-bootstrap in Angular 8.

Ngx-Bootstrap has released a package of open-source tools which is native Angular directives for Bootstrap 3 and 4. It contains all core components powered by Angular. In this article we will learn about Typehead component which is a cool feature of Ngx-bootstrap.

What Is Progress Bar?

A Progress bar is a component in GUI which is used to visualize the progression of a task which is completed, such as the percentage of amount that is completed during downloading.

In Ngx-bootstrap progressbar there are normal, striped and striped with animated striped progress bar.

Prerequisites

  • Basic knowledge of Angular
  • Visual Studio Code must be installed
  • Angular CLI must be installed
  • Node JS must be installed

Step 1

Let’s create a new Angular project using the following NPM command,

 

Step 2

Now, let’s create a new component by using the following command,

 

Step 3

Install ngx-bootstrap from npm by using the folowing command.

Or,

Step 4

Now let’s add bootstrap styles in our index.html file .

For Bootstrap 3,

 

For Bootstrap 4,

Step 5

Let add the template in our ngx-bootstrap-progressbar.component.html.

Step 6

 Now, open the ngx-bootstrap-progressbar.component.ts file and add the following code in this file.

Step 7

Now, open the app.component.html file and add the following code in the file,

Step 8

Let’s open app.module.ts file and add the following code in the file,

Now it’s time for the output,

 

 

This is the normal progress bar which we can use with different bootstrap supported contextual classes : success, info, warning, danger

This is the striped progress bar which has striped lines to show the amount of tasks done. 

This is the animated progress which looks like it is in progress .

Though we can use these progress bars dynamically we just want to replace the value field with our dynamic variable. 

Conclusion

In this article, we have seen the Ngx-Bootstrap progress bar Component in an Angular 8 application.

I hope you have enjoyed this article, as I have enjoyed writing and coding the examples.

Please let me know how to improve it.



Source link

Book: The Greatest CSS Tricks Vol. I
Strategy

Book: The Greatest CSS Tricks Vol. I


Ya know, for a site called “CSS-Tricks” that I’ve run for well over a decade, it’s a little funny we’ve never done a book under that name. I’ve written a book about WordPress and SVG, but never CSS!

Well, allow me to change that. I’ve been working on a “book” called The Greatest CSS Tricks Vol. I, as my attempt to stay true to this site’s name! The big idea to make it like a coffee-table book for CSS, where each chapter is totally independent and talks about one literal CSS trick that I’ve found to be exceptionally clever and useful. A book about quite literally the best CSS tricks I’ve come across over the years.

I quoted the word “book” above because this is the loosest possible definition of a book. I have not yet made it into an eBook format. I have not even considered printing it yet (although there is a “full book” URL available with the whole book together for printing and print-to-PDFing). This book exists as URLs which are essentially fancy blog posts grouped together. I’m also calling it Volume I as there are already ideas for another one!

Some chapters are fairly broadly known concepts that I’m writing up to put a point on. But many of the chapters are based on ideas that can be traced back to individual people and I always try to credit them directly.

Here’s the chapter list so far:

  1. Pin Scrolling to Bottom
  2. Scroll Animation
  3. Yellow Flash
  4. Shape Morphing
  5. Flexible Grids
  6. Border Triangles
  7. Scroll Indicator
  8. Boxy Buttons
  9. Self-Drawing Shapes
  10. Perfect Font Fallbacks
  11. Scroll Shadows
  12. Editable Style Blocks
  13. Draggable Elements
  14. Hard Stop Gradients
  15. Squigglevision

I say so far because I might add a few and rearrange them and such, not to mention it could still use a healthy bit of editing. But I think the bulk of the value of the book is already there.

Value? I think so. While it’s fun to learn some CSS trickery, I think there is value beyond the tricks themselves. Tricks help you see how CSS works at a deeper level. When you understand the trick, you’re seeing how that part of CSS works through a new lens and it helps you be more in tune with the nature of that CSS. It will help you reach for those CSS properties more intuitively when you know what they are capable of.

In another sense, it’s like taking a walk with weights in your backpack. You do it on purpose so that when you walk normally, it feels easier. The tricks are like mental weights. They make writing non-tricky CSS feel easier.

So about buying the book. You don’t buy the book directly. What you buy is an MVP Supporter membership to this site. When you’re an MVP Supporter, you have access to the book, and more. This is the whole package:

  • No Ads. You see no ads on this site, except for sponsored posts which are just blog posts and I try to make useful anyway.
  • Extra Content. You can read the digital books I’m making (you can already read some chapters, but they are under progress.)
  • Easier Commenting. You’ll be logged in, so leaving comments is easier and won’t require the delay for approval.
  • Good feels. An extreme sense of satisfaction of supporting this site and our commitment to bringing you useful tech knowledge.

It’s just just $20/year.

Have I, or this site, helped you out over the years? This is the best way to say thanks.

Also, if you would really like to have access to read the book, and can’t afford it right now, I totally get it. Email me at [email protected] and we can work that out.



Source link

SalesForce development economy
Strategy

An Introduction to the Serious Stack Behind Salesforce Devel…


My Salesforce Developer Journey

I’ve been developing software for thirty-five years. In the late 2000s, I was a heads-down developer writing business applications for my customers with Microsoft technologies. A decade before that, I was working with early HTML, JavaScript, Java, ColdFusion, and Lotus Notes. And through the 1990s, I was building desktop database apps with FoxPro and Visual Basic.

About ten years ago, I was starting to burn out when I stumbled onto what was then known as Salesforce’s Force.com (now known as the Lightning Platform). It was like discovering new love. At that time, cloud computing had only just begun to catch on, and there were few platform services offering similar capabilities. None matched Salesforce’s scale, flexibility, depth, and breadth.

Unlike other technologies of the time, with Salesforce I could build an app in a day and deploy it to thousands of users almost instantly. I could modify the data schema, logic, and user interface while they were live in production without disrupting any user. I could integrate with other systems using pre-existing, robust security mechanisms and industry-standard SOAP and REST APIs. And I couldn’t even count all of those pesky IT tasks that I no longer needed to worry about as a developer. And it was fun! Working within the platform was enjoyable and made it easy to find success as a developer.

In short, I fell madly in love with the technology and never looked back.

Today

Fast forward to 2020. I remain immersed in Salesforce technology, where I have been building business applications and solutions since finding the platform ten years ago. I subsequently directed my career toward helping others learn and master Salesforce technology as an instructor and mentor, focused on helping other developers leverage the platform for their own success.

In my eight years as a Salesforce MVP and ten years as a Salesforce Training Partner, I’ve been asked by customers, students, and fellow community members what exactly compelled me to migrate to Salesforce. After all, I was a data-centric business application developer, and Salesforce was for CRM. I didn’t even know that CRM meant (Customer Relationship Management at the time!)

Over this series of articles, I’m going to answer that question. I’ll talk about why you should consider Salesforce development as a career and the unique career opportunities (both technical and personal) available to both experienced and beginning developers. I’ll talk about how the platform is financially rewarding because of the ever-expanding customer base, the ever-expanding technology, and the dearth of experienced development talent. Most importantly, I’ll explain how the platform has evolved into a deeply-technical developer platform that requires serious developers.

SalesForce development economy

But Isn’t Salesforce Just for CRM?

First, let’s address the question that has been a huge point of confusion and a key impediment to many developers taking advantage of the platform. No, Salesforce is not just CRM. Yes, it’s true that Customer Relationship Management (or CRM) is the core of Salesforce. However, in service of building and evolving their CRM platform, a resulting side-effect has been an enterprise-grade, metadata-driven, multi-tenant cloud architecture that allows developers to build almost any kind of business application. 

Customer data is the heart of Salesforce, and the heart of most business applications. Salesforce customers who already use the CRM now have a complete application development platform at their disposal, which can be used to rapidly build whatever innovative business applications they can conceive: financial, task management, contract management, document workflows, eCommerce, mobile, and more. 

It enables building applications quickly, with a cloud-first stack supported by the serious development frameworks you expect in a modern system: an open-source web components UI layer (Lightning Web Components), integration with DevOps tools such as CI/CD pipelines and containers, an AI engine (Einstein), a platform message bus (Platform Events), and there is evolving technology (Evergreen) for serverless microservices using Node.js, Redis, Kubernetes, and more.

Should You Become a Salesforce Developer?

So let’s look at the market. There is a strong and growing market need for Salesforce developers. Salesforce developer was named a top-10 job of 2019 by Indeed, with a 129% year-over-year growth and an average salary of over $117,000. Why? Salesforce is used in over 90% of Fortune 500 companies. And more and more of these companies are migrating their non-Salesforce apps into their Salesforce ecosystem. In order to succeed, these companies need developers familiar with both Salesforce and traditional development stacks, and here is where I found great opportunity.

As in traditional development, the Salesforce platform needs a wide range of developers with a wide range of interests. Let’s see how it might align with your skills.

Front-End/JavaScript Developer

Are you a front-end web developer working with HTML5, CSS3, and modular JavaScript? Are you intrigued by web components and building beautiful and responsive business applications that present consistently across desktop and mobile devices? These skills are in high demand within the Salesforce ecosystem. Over the last few years, the platform has adopted web components and modern JavaScript industry standards for its Lightning Web Component framework and the modular component-based architecture behind its Lightning User Experience. 

As a side note, they’ve also embraced open-source standards by creating a variety of open-source projects, such as the Lightning Web Components project, oclif — a framework for building CLIs in Node.js — and Apache PredictionIO — a machine learning server — and more.

Full-Stack Developer

Maybe you’re hooked on Node.js and JavaScript libraries and frameworks. If so, there’s great need in the application stacks that lie beneath the Salesforce clouds. These proprietary applications in their eCommerce, Marketing, and Price Quote products utilize such web technologies for their customization— and Salesforce is all about customization.

 JavaScript plugins for Salesforce

Maybe you’re more interested in relational databases, stored procedures, and object-oriented service layers. The Heroku platform allows for managed data stores like Postgres, Apache Kafka, and Redis supporting all sorts of web applications and easy integration with the Salesforce database. And while the Salesforce metadata-driven cloud architecture allows non-programmers to configure the core Salesforce data object schema and configure no-code logic processes, more complex business requirements often require programmatic triggers and service logic written with the Apex object-oriented programming language.

Apex programming language

Microservice or Serverless Architect

While in-bound and out-bound web integration has been built into Salesforce for well over a decade, the Evergeen toolkit will allow Salesforce developers to write small functions and microservice logic using not only Apex, but also Java and Node.js. This allows them to be invoked natively from within Salesforce, using both declarative and code-based tools. The Heroku cloud platform already supports polyglot web applications and services that easily integrate with the native Salesforce clouds, and Evergreen will expand these capabilities even more, providing a whole new opportunity pipeline for developers.

 Evergreen System Design

Mobile Developer

Perhaps you’re an iOS or Android mobile developer. While it’s true that native Salesforce is configurable with no-code to present on mobile devices, available SDKs allow for truly native mobile and device app development for custom business cases across all sorts of business domains.

Artificial Intelligence/Data Scientist

Or maybe you lean towards business analysis, analytics, or artificial intelligence. Salesforce Einstein provides opportunities for developers interested in data science, analytics, AI, and integrations across external transactional business systems. Salesforce also recently acquired Tableau Software and has standing partnerships with both IBM and Microsoft.

Tableau dashboard

Solutions Architect

Even with highly configurable Integration Cloud tools, such as Mulesoft, there is still a great need for solutions architects with integration and identity skills and experience. The platform follows an API-first approach, and built-in, standards-based identity management mechanisms allow for highly-secure application and service integrations. Yet again, even though much can be accomplished with no-code configurable tools, solid developer skills are still required to build and maintain effective integrations across any enterprise landscape.

Integration pipeline

IoT Developer

Maybe you like to play with connected stuff. An API-first company would be a great platform for Internet of Things (IoT) applications. Salesforce has been evolving its IoT offerings to support opportunities for customers needing machine-to-machine communication across a wide variety of industries, such as manufacturing, agriculture, medicine, and energy — all ripe opportunities for developers with “Maker” propensities.

My key point is that even though Salesforce is famous as a no-code platform, the reality is that there’s an industry need for traditional developers who can effectively apply their skills within the ecosystem. While it can be challenging for developers to merge programmatic logic with declarative mechanisms, that’s one aspect that creates such high demand for those who can master such skills.

What’s Next?

Over the next few posts in this series, I’m going to drill down into some of these technical areas. Along the way, I’ll provide links to where you can find deeper information, online educational content, and documentation. I’ll freely admit my goal is to entice you to learn more — and maybe even convince you to jump in.

In my next post, I’ll focus on the core aspects of the platform and what it means to be a Salesforce Business App Developer. We’ll look at some of the App Dev capabilities of the platform, the power and leverage of the metadata-driven architecture, the need for sophisticated development skills to work within such an architecture both declarative and programmatic, and more.

I hope you’ll come with me on this Salesforce Developer Journey, and I’m going to hope (and maybe even bet) that it could change your life as it did mine.

Published with permission from Don Robins.



Source link