Optimise Sprite CSS for multiple images - optimization

Had a few problems getting background-image displaying in Firefox, I made it work but was surprised at how bloated the CSS became. It now works great, but I need to replicate base CSS code for multiple images.
Can anyone tell me if it is possible to optimise the CSS classes and minimise the amount of code. I cannot utilize the already used id's, and class='imga p0' doesn't work (where p0 just holds the background-position, becoming p1, p2, p3 .. for each image position).
Thanks in advance for any advice.
a.imga0 {background:url(../images/sprite.png) no-repeat;background-color:transparent;
display:block;width:24px;height:24px;background-position:-288px 0;} /* tick green */
a.imga1 {background:url(../images/sprite.png) no-repeat;background-color:transparent;
display:block;width:24px;height:24px;background-position:-312px 0;} /* cross grey */
a.imga2 { ..... and so on.

Edit:
So this should eliminate the repetition
/* template */
a.imag0, a.imag1, a.imag2 {
display: block;
width: 24px;
height: 24px;
background:url(../images/sprite.png) no-repeat;background-color:transparent;
}
/* specifications */
a.imag0 {
background-position:-288px 0;
}
a.imag1 {
background-position:-312px 0;
}
For one you could create a general selector
a {
background:url(../images/sprite.png) no-repeat;background-color:transparent;
display: block;
}
Which would apply the general style, such as the sprite image.
You could also create a separate class (specify more classes with spaces)
So for example, you could have
<a class="imag0 spriteclass">something</a>
<a class="imag1 spriteclass">something</a>
<a class="imag2 spriteclass">something</a>
And
a.spriteclass {
//again the template, such as the sprite and display type and width
}
Your second option is to list out the selectors you want the css to apply to,
a.imag0, a.imag1, a.imag2... {
// your general css
}
And then like above specify the specific sprite positions and details separately

Adding this just in case some one refers to this post later.
You can generate the most optimized CSS using this below tool.
http://www.spritecss.com/

Related

Ionic4 Print Media Query for Scrollable ion-content

Pretty straightforward problem. Have scroll-able ion-content in my Ionic4 application. I want to be able to print it gracefully by applying #media only print styles. I'm almost there, but I have one major problem. I cannot get the vertical scrollbar to disappear for printing. Additionally, I only ever get one page printed, containing only the content that is in view when I print the page. I've scoured the web for solutions, and come across and tried various suggestions in the context of Ionic3 and earlier, but I haven't found the magic bullet for Ionic4 yet. Has anyone encountered and gotten to the bottom of this yet?
I have been through the ringer on trying to print content in Ionic 4. Some of the steps i followed to print multiple pages.
remove any flex-box styled lists. They just will not print how you want them to across pages, though they have worked fine for me if the content fits in a page.
for items you want to be seperated by page, its best if they are a display: block; styled item, so that that in the print style sheet you can use one of the page-break properties on it
on the item containing your list, the ion-content for example, make sure you remove any max-height attributes from it or any of its ancestor or child elements, as well as removing the overflow: scroll from these elements as well so that it allows your content to go from page to page. for example on my stylesheet for printing (cant share it because of NDAs) I had a lot of overflow-y: visible on elements just to make sure it shows. if you find an element thats cutting off your html, it should be the primary target for experimentation.
you can simulate a print in the dev tools, i found it useful, it's good for iteration here's a link
some other things that may help, but i am not sure as I did so much testing across browsers, and only vaguely remember what impact that css property had is to have the body with a static position, as well as having contain: none on the body to say that the browser should render as normal, little more explanation here
i do not know the specifics of your use case, but if you don't mind foregoing the native print button, and just giving the user a button to click to trigger the print, then that would be more manageable as you do not have to account for all the scaffolding around that specific element that you want to print (the ion-router, ion-page, and all the ancestors)
If you did that then you could put all your items you want to print into a div with an id of printSection or what you prefer, and then the javascript that is responsible for that page you can create your own print function. In my example i will use angular, if you are not using that then preform whatever DOM selecting you need to to get the native html out of your template.
#Component({ ... })
export class Page {
// select the item holding your print content by `#property` you gave it
#ViewChild('printSection', { read: ElementRef }) printSection: ElementRef;
...
customPrint() {
const printContent = this.printSection.nativeElement;
const WindowPrt = window.open('', '', 'left=0,top=0,width=900,height=900,toolbar=0,scrollbars=0,status=0');
WindowPrt.document.write(printContent.innerHTML); // pass in the native html you got
/**
* you should probably use an observable instead of an interval for this,
* but this is just to illustrate a bug where the print would be fired before
* all the content was written
*/
const interval = setInterval(
() => {
if (document.readyState === 'complete') {
WindowPrt.document.close();
WindowPrt.focus();
WindowPrt.print();
clearInterval(interval);
}
},
200);
}
}
I Solved it following this process
First, remove the content to be printed from ion-content. Use a div instead of ion-content(shadow-dom is implemented with ion-content which blocks your CSS classes)
You also need to force the CSS below on ion-page when printing (it is initially set to position: absolute, by default)
In my case I was printing from a modal component which has a default class "show-modal". I was able to print on multiple pages by target that class this way
#media print {
.ion-page {
left: 0;
right: 0;
top: 0;
bottom: 0;
display: block;
position: relative;
flex-direction: column;
justify-content: space-between;
contain: none;
overflow: visible;
z-index: 0;
}
.scroll-content,
ion-modal.show-modal,
ion-modal.show-modal .modal-wrapper,
ion-modal.show-modal .ion-page.show-modal,
ion-modal.show-modal .ion-page.show-modal > ion-content,
.ion-page.show-modal,
.ion-page.show-modal > ion-content,
ion-tab,
ion-tabs,
.app-root,
body {
contain: none;
position: relative !important;
height: auto;
overflow: visible;
}
}
I'm also trying to solve this same issue. I've scoured the Internet, and tried many an idea, but none has worked so far.
Perhaps we could solve this collaboratively. I'd put this as a comment, but I don't have enough rating points, so the system will not let me.
This is what I've found so far. In Chrome Developer Tools, you can click on a settings icon, then scroll to "Rendering," and on "Emulate CSS media type," select "print."
When I do that, it shows what the print view is. I created a separate css file, let's call it print.css, and in it, there is
#media print {
/* add your css styles for print here */
}
I know my print.css is being processed because I've
display: none
for ion-header and some tabs at the bottom, and they do disappear when I select "print" emulation in Chrome.
What is interesting is, I'm seeing the whole page -- scrollable and all -- on the screen in this print mode. However, every time I try to print it, only one page shows up.
That page, however, doesn't always start at the top. It includes the current viewport.
Which is why, I'm wondering if there is something in the css that is trying to keep the whole thing as a page. i.e., preventing a page break?
I'm experimenting with things like this:
ion-content, .foo, .bar, ion-list, ion-tabs, ion-item {
break-inside : auto !important;
break-after : auto !important;
break-before : auto !important;
}
(where foo and bar are classes you might have of your own.)
This above one breaks things. Removing ion-tabs, ion-list, and ion-item shows the full page.
I'm also experimenting with the following. None has worked so far, but that is probably because I haven't selected the right tag or class.
display: block !important;
height: 100%;
overflow-y: visible !important;
max-height: unset !important;
contain: none;
You may want to experiment with the tag in question that might be preventing a page break. Some people are suggesting it's flexbox or grid that's the root cause. I'd love to know how to find the root cause.
Good luck! If something works, let us know, so I'll also try it in my code.

Dividing a text into multiple pages

Currently, I'm creating an application where my client creates invoices and offers. To let him create an offer, I'm using CkEditor. This all works fine but he's also able to export this offer to a PDF-document. Sometimes he sees that some text divides into multiple pages. Because of the fact this sometimes happens at places he don't want this, he asked me to create a function that shows him a page divider while editing.
What I've done now is showing an image (position absolute, behind the text) on a calculated position, 1700px from top or from the last divide-image. For some reason I think this could be better, what do you think is the best way to do this?
Example:
http://i.stack.imgur.com/Q2a7w.jpg
Try if your pdf generator respects page-break-before, page-break-after and page-break-inside.
#media print {
/* Always start a chapter on new page. */
h1 { page-break-before: always; }
/* Keeps lines together */
p { page-break-inside: avoid; }
/* A custom page break element. */
/* Add styling for editing but hide visibility in the rendered document. */
hr { page-break-after: always; visibility: hidden; }
}

LESSCSS: Assign a value to a property taken from another one's

In some cases is common to use same values in different properties, for example (is just an example to show purpose) the following nested rule:
.button-link
{
height:40px;
a
{
line-height:40px;
}
}
The idea is that to vertically center button text line-height and height should be equal.
Is there a way in LESS to "assign a value taken from a diffent property"?
I know that I should use a LESS #variable but in this case is not the same thing and need extra code. Instead should very interesting and useful if I should edit only button's height and then LESS will replaced the same value to line-height
UPDATE:
Another example could be the following:
.button-link
{
color:white;
background:black;
&:hover
{
color:black;
background:white;
}
}
In which "hover" status should invert color and background-color comparing to default state.
This is possible starting with v3 of LESS! Here is the documentation on it.
The example use case they provide ends up with the background-color getting the same value as the color property when compiled:
.widget {
color: #efefef;
background-color: $color;
}
You can´t :(. What i usually do is:
#buttom-height = 100px;
#a-link-height: #buttom-height;
and use that variables in your less declarations. Its a dummy example, i know, but imagine calculated data values from other variables or complex dependencies, proportional paddings/margins... that´s the way i learnt from Bootstrap LESS code.

Bootstrap 3 - remove breakpoint between md and lg

I'm using Bootstrap 3 and trying to remove/exclude the breakpoint between medium and large devices. I have a existing website which is optimised to 970px which looks great. What I am trying to do is remove the md > lg breakpoint so that even on large widescreen desktops the maximum body width is 970px and still centred.
Anyone know if there is a quickfix solution to this?
Any advice would be much appreciated
Decbrad
If you're overriding the bootstrap breakpoint (and using containers properly), adding this below the bootstrap breakpoint media queries in the bootstrap CSS file should work for you.
If using LESS
#media (min-width: #screen-lg) {
.container {
width: 970px;
}
}
OR, you can simply override the bootstrap container in your own CSS (just make sure you load it after bootstrap.css)
#media (min-width: 970px) and (max-width: 2500px) {
.container {
width: 970px;
}
}
OR you can find the media query in the bootstrap.css file on around line 1240 and simply change it there
#media (min-width: 1200px) {
.container {
width: 1170px; /* change 1170 to 970 */
}
}
the less way is good but this one is more flexible and reliable:
#media (min-width: #screen-sm) { .container { width:#screen-md; } }
Because in bootstraps default values the width of #screen-md is 992px.
Now you will just have a breakpoint for small devices (smartphones) and any other bigger devices. they will all get the same layout
You can set a max width on the containers:
.container-fluid,
.container {
// Disable large-desktop breakpoint.
max-width: $container-md;
}
No need for media queries or anything.
The $container-md value is typically 970px, unless you changed the $grid-gutter-width. For LESS, replace the $ of variables with an #. For regular CSS, replace the variable with the hard coded pixel size.

Can a mixin refer to values in the calling selector?

For example, I would like to be able to do this:
.bigfirstletter(#mag) {
&:first-letter {
font-size: [get_original_font_size] + #mag;
}
}
But as far as I can see I have to do this, which is not as neat
.bigfirstletter(#fontsize, #mag) {
&:first-letter {
font-size: #fontsize + #mag;
}
}
Do I have an alternative? Thank you for your help.
damn it was simpler than I thought :)
.bigfirstletter(#mag) {
&:first-letter {
font-size: 1em * #mag;
}
}
1em will simply inherit whatever it is defined for element, and you just set your magnification. I changed the plus sign to multiply on purpose as with this you're going to have better control over font size - #mag=1.0 for same font size, #mag=1.5 for 50% bigger, and so on..
sorry about the answer below, for some reason I didn't see that you're using first-letter in the example provided (doh!)
take a look at :first-letter CSS pseudo class - here