I'm doing a website which displays lots of little icons (stars, flags, folders...)
Now I'm using the CSS sprite technique and it works great but it's hard to mantain.
I'm thinking on making a big .js file with all images encoded as javascript variables. Then display the images this way:
images.js
var myimage1 = 'data:image/png;base64,iVBORw0KGgoAAAANS...';
var myimage2 = 'data:image/png;base64,cB324CD64aB3Cme23...';
html code
<script type=text/javascript src=images.js></script>
....
<img src="javascript:myimage1">
<img src="javascript:myimage2">
I know that the .js file would be bigger but it's very easy to maintain and it will be cached by the browser.
It's a good or bad idea? Is this cross-browser?
Stay with CSS sprites. If your users have JavaScript disabled, they won't see the images.
If you decide to stick with CSS sprites (because you require IE6/7 support, for instance, or are concerned about no-JS fallback), a few things that might help with maintenance:
Organize sprites into separate images based on shape. For instance, put all of your 20x20 badges in the same sprite, all your 30x15 folders in another sprite. (Yes, you will have more HTTP requests, but HTTP performance is one of many factors to consider.) This makes calculating CSS much simpler. You can set the sprites up as single columns, double columns (which is nice for roll-over effects) or whatever keeps things cleanest. Dealing with a large, irregular sprite is a pain!
Have a low-impact pattern for adding new imagery. Always add new items to the bottom, for instance, so you don't need to recalculate CSS for imagery above the new image. (This really only makes sense if you organize sprites per my first point.)
If you are no longer going to use sprites, just blank them out. Leave white spaces or gray x's or something in their old spot. Then when you have time and a bunch of removed images to clean out, do them all at once. (Again, if you're crazy concerned about performance, you might not like the idea of leaving any spare bytes in these files...)
Just a few thoughts.
Just think, would you rather see this:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAIRRJREFUeNrs3U%2BMHNd9J%2FAaznANcSmTkHSgnZHCQ0QqOZFG7EtgZxAjlwWI6BRgb84e9rILOL5sDjmIPiywe7IDJMckvgXJScYAuQSOm174IgEieRI51qHJoSUCO2OTonYocbq7tqs5TQ9p%2Fpnuqa5Xr36fD9AQfPGwX3VVfd%2BrX%2F1eUZCbn44%2F5YI%2BFxfw7724wH%2FvT1vwb8jhc7El4%2FTr8ed0w%2BfL2w2M71pLzofS5ZFZHDEEQENOjj8%2FaPjv%2FaNhBwEASO%2FtvU8T3tkLAYAAALTADxq4MZ8bf%2F7SUIMAALTH6QZuzj8wzCAAAO3zTrG4gsDvFLMV5oEAANCgRRToNV1oCAIAwIyqWXrdBYFN1BeAAABQwypAXTfsKlB8x5CCAAC0X3Xzf6fG2T8gAACZqN4IONeC%2Fw8QAAAadpjZe52rCCAAADRorZi%2FN0CddQQgAAA0bJ7WvVVweNvQgQAA5Gued%2Fht9gMCANAB3ykO3sXvYtH89sIgAAAsyEFWAaob%2F3cNFQgAQHec25vdP4%2FCPxAAgA76bvHs5f2q6G%2FNEIEAAHTPswoCbfYDAgDQcU%2Bb6f9lofAPBACg8%2Fa%2F5lfd%2BHX8g5qsGAL2%2Bd2i%2Fmerv2tYOYTqpn9x7%2BOdfyC0n44%2Fpc%2Fk89NEx2Btwd9rLdH3utjiY93mf9tai8YYDswjACAHlv5BAAAABAAAQAAAAAQAAEAAAAAEAAAQAAAAAQAAEAAAAAEAABAAAJ6rn%2FBv3xl%2FrjgEIAAAzfve3o042t8GAQAI7c7ejbhpvfHnR4YfBAAgnR%2Ft3ZCbDB1%2FYdhBAADS%2B4uiueX47xdpaw9AAADY09%2B7MS9ab%2Fz5oeEGAQBojx8Wi38U8D3DDAIA0D6LvEFXKwxe%2BwMBAGihK8ViHgVU%2F78XDS8IAEB7XVzATF3VPwgAQAbqvGH%2FsLD0DwIAc6mWZJdq%2FnzfsPIcV4p6qvX7fmsTZeLPRYdAAACYJXj2a1hJ0O4XBAAgI4ft2NfEa4UgAAAsQK%2BY71FAFR4s%2FYMAAGTs%2B8Xsy%2FiW%2FkEAADI366OAd%2Fc%2BgAAAZO6gN3U7%2FYEAAHTMQZb1v1dY%2BgcBAOiUO8Xz9wrojT8%2FMkwgAADd86Pi6a%2F2WfoHAQDouKc9CqijaRAgAAAt1i8ef8e%2FWhH4oWEBAQDovv1d%2Fr5nOKA%2BK4YAaLnqxn%2B6sNMfCABAKFfc%2FKF%2BHgEAgAAAAAgAAIAAAAAIAACAAAAACAAAgAAAALTHkiHIzrnx5%2BSC%2Fr%2F7Rf0brZze%2ByxCtVFMigYxJ%2FeOw6JcKdLsdb%2FIY5XqOzVx3szy3RY5xm2wiGsIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQWkuG4GBuXTizNv7PmpEAaLXe6vpGzzC82IohOLDq5v%2BOYQBofwgwBC92xBD4QQG4VgsAAIAAwD53DAGAa3VXKAKcwa0LZ0qjANBeq%2Bsb7mtWAAAAAaAelpYAXKMFgICuGAIA12gBAAAQAALoGwIA12gBIJ4bhgDANVoAAAAEgAAUmAC4RgsAAXnFBMA1WgAAAPKkZeKMtAMGaCdtgK0AAAACAAABeP4vACxczxAAtI43AAQAAEAAqJ9lJgDXZgEgoKuGAMC1WQAAAASAAPqGAMC1WQDwIwPAtVkAAAAEgC7yrimAa3P29E2eg%2F0AANrFPgBWAACAA1gxBHPpjT9rhoHcLf8HkybqUw7LYjRMdk1GAAAO6tgrFgGpz%2F07o3EA8IQ0F85%2BAOpZARgl%2B9PaAAsAjblkCABaQxtgAQCAVIYPLP8LAN1nuQnANVkACEjDCYB9yrSTf9dkAQCAFEa7lv8FgBj6hgDANVkACGZ1fcOPDWCflI8AXJMFAAASGe0aAwEgDkUnAK7FAkBAXjsBmK4ApGsB7FosAACQLgAYAwEgDu2AAVyLBQAAAq8ADPQBEAAACMdOgAJAJD1DAJCctwAEAABSsAugABCNZScA1%2BJsLRmC%2Bd26cEbsJWsvn1o2CBza4IuyuP%2FrNEUAq%2Bsb7mNWAABIQRtgASCiviEAcA0WAPz4AMIp020F6BosAACQytAjAAEgIO%2BfArgGCwAB3TUEQHRlup0AXYMFAABSsROgABCR5SeAdHqGQABIRQcqIPbs3y6AAgAA8STcBdAk7JC0UDwk7YDJmVbAHFa1EdDOr7QBtgIAQLAAYAwEgLgsQQG49goAAXkTAAgrYRtg114BAIBUtAEWACLrGwIA114BIJ4bhgCIKt0TANdeAQCAZEa73oQWAOJSiALg2isABORVFCDm7D%2FtJkCuvQIAACkk3AYYAaAVLEMBNGx1faNnFASA1D9Cy1BASMOBMRAAAIgn3U6AJl4CQGv0DAFAYzx6rcGKIWAeR%2F%2Fqbw1C7if%2F8krxH185biAyN9z8sPj8n%2F9Xkr89eKAIUAAg3HLUkdffLIpjbh45Wz56tFg%2BccJAZG609UvXXOa7jhuCWlwNd9HZ%2FIWjDm04F7fTBYCEbYCvOvICAACpwoc2wAIA8XalKrc%2BcdShBYab11xzEQD8GBu0ddtRhza4fy%2FNJCDt5F8AEAAASMHyvwDAQ%2BHeSR3dVAQIbTC4%2Fp5rLgJAKiHbASdadgRaMglIuBOgFuwCAACJlENjIAAwFWpJyiMASG%2B48X7Er91z5AWAtom1JLXzmSMOkcPHQBGgAABAEuXOp%2Bn%2Btp0ABQAeuRTtC4%2BuX3bUIeUsPGYTIG2ABQAAkoUPOwEKADwSb1lqx6uAkFLKjYBcawUAfiNcY4ry5keOOqQ8B7c%2FTvN3007%2BNQESAABIQRtgAYDH9cPNPuwICEkNNz90rUUASG11fSNeANgWACDpObgTbyfAiNdaAQCAVhjtGgMBgCeFSqbaAUM6QdsAKwAUAASAVtAOGGKuAAyTPQPwCqAAABBbyjbAIzsBCgD8loC9ADwGgBSCtgG%2B5MgLAG11N1wAuO8xAEQzshOgAABAovCdsBV3wp0AEQBaqxfuInTNjoCQZBZ%2BK%2BQjgJ4jLwAAkIBdAAUAni7cKyqlHQEhzQrAlp0AEQBaY3V9I95bAJveAoAkASDRVsCJ2wBrBCQAAJAkeGgDLADwTP1QKwBbtx1xaFjQHgB9R14A8CNtVQCwIyA07n7CVwDTPQMQAAQAAFIZegQgACClWgWANAbX34v4tRUACgCtdyNcANhWBwBhzvd0OwHeNfoCAEDsm3DC%2Fht2AhQAeDY7AgKLvQlrA4wA0ErxOlXt2BEQQgQPuwAKAAAkvBEnagNsF0ABgOdYXd%2FohbsYXf%2FAgYcmz7ntePsARLy2CgAAtMLwgTEQAHiRUHUApRoAMPt3TRUAmAj1JoC3AKDB823743R%2FO10bYE2AFmDFEBB6NnX9ctjvPlxeKYavHPcjyO24bX6Y7m9rAywA8ELhlquqdsBLr30lu3%2F37v%2F%2B72F%2FpNW1fOXUsrOVHPQNQf08AliMq%2BECgHbA0P3zPF0bgBtGXwCAWi298aZBgAMa7WoEJADwIv1wM4NMdwRcOuYZOGRAEaAAIAC01pZHANDp2X%2FaTYC8BigAQM0nwNmvGQQ4gITbACMAZCXcctVILwBgQbQBFgBy%2BrHGW666f8%2BBhw4bDoyBAAAdsvTWeYMAB2EnQAGAA%2BuFujZcu%2ByIA66lAgBksgLwktcA4SAGDxQBCgAcVLw6gAx3BdQICFxLBQDqFq4d8GjTmwDQVQnbAF81%2BgIALGYVIMNNjKDxgK8NsADAgYXcETDPAHDKrxXaq28IBIDcxOtdrR0wdDPcp538CwACACxoBeB1hYDwPJb%2FBQCk1ufPErLdEfBlv1ZoLzsBCgB5WV3fiBcAtj9x4KGLKwAJdwIM2VpdAICGVgC0A4bnh%2FuhMRAAmFWopSs7AgI16xkCASBXsZauMuwECLzYcKAIUACALp4EZz0CgOcp7QQoADCzS9G%2B8Oi6XQEB11ABAHJxzK6A8CxDOwEKAMws4I6A9%2FI8EewKCK6hAgA1CtfAorz5kaMOXTqn007%2BNQESAGCxll61IyA8jTbAAgDzibcjYKaPAGwJDK3UNwQCQJZW1zfiPQLY1AwIOnVOJ1wAiNhSXQCAplcA3vg9gwBPMdo1BgIA8wqVYMut23n%2Bw%2B0ICG2jAFAAEADyCgB2BIROrQAMkz0D8AqgAAANnAjaAcMzAoAxEACYV8BeAAoBgUPTBlgAyN7dcAHgvl0BoTMrAHYCFACg8yfDWx4DwG8FejsBCgDMrRfugnHNjoCAa6cAALl4yauAsJ9dAAUAmG0FwI6AwOF5DVAAyNvq%2BkYvXADQDhi6cS6nbQOsEZAAAA157ZQxgH20ARYAOLxQS1nlTp6vAdoREFqjbwgEgK4ItZSlERB05FxO9wxAABAAoMGT4XVFgLDf0CMAAQBpduaZQ46bAh077pcK7aAAsAErhqARN8IFgO3bWT5T%2F9I%2F%2FDzMMTp69Gjx5RMnnJ0t98X6300%2BSc7jdDsB3nXkrQAAkIidAAUADs%2BOgMBchhvvR%2FzaPUdeAOiKeB2tduwICFnP%2Fu0CKAAAkE6582mav2sXQAGAw4vYDnh0%2FQMHHmow3LzmmokAAEBDweOBMRAAYA6lGgA4tNH2LyN%2BbbsACgCd0wsVALwFAIc%2Fj7Y%2FTve307UB1gRIAAAgFW2ABQDq41VAYLab8OaHEb9235EXALrmarQvPNr0GAAOo9y5l%2B5vp2sDcMORFwAASBXgdzUCEgCoSz%2Fc7CXHHQGhRYK2AVYEKAAIANnbuu2oQ46z%2F7SbAHkNUAAAiC1ZG%2BCh5X8BgDqFW9Ya6QUAh6INMAJAN37U8Za17t9z4CHH4DEwBgIAAEkkbQNsJ0ABgNr1Ql3Arl12xGFOKdsAu0YKAAAENHigCFAAgMPSDhjmMtqyEyACQJdcCncR0w4Y5jt3Ym4FfNWRFwAASGToEYAAQO0C7gjoVUCY6yYcsAdAYSdAAaDDwjUDKm9%2B5KjDPBL10SjTTv4FAAEAgBTsAigAIN3WM5uwIyDMZXD9vYhf206AAkA3ra5vxAsA2wIAZLUCkHAnwJAt0wUAAB4F54TFs%2BXQ%2BAsALEqoJS47AsIc582tkG8A9Bx5AaDrYi1x6QQIWRkOFAEKAACkWQFI2Aa4tBOgAMDChKtyHV23KyDMdM7EbAN8yZEXALruriEA2kobYAEAACsATfIKoADQeb1oX7i85hEAzHTObH8c8WtrAiQAAJCC5X8BgMUKt8xV2hEQZrsRb34Y8Wv3HXkBoNNW1zfi7Qi4qRkQ5BCaU%2B4EGLFVugAAQCuMdo2BAMCihUq65dZtRxwOaLjxfsSvrQBQABAAuhkA7AgIWawADJM9A%2FAKoAAAEFu582nCAGD8BQAWLV4hoF0B4UCGmyF3AtQGOIEVQ5BEuHbA1X4AS%2FftDNiqG83ySjF85Xhnv9%2FSq18tjrz6Ow70LOepnQAFAKjb4J%2F%2BxiC0TFXwvXJqubPf70sX%2Ftvkk91NeNtOgDTDI4A0VLwCT78Jx2wD3HPkBYAoVLzCoi9ulv9nog2wAADQjYvba3kGgNGWnQARADprdX2jZxSApwaAgFsBR2yRLgAALOritvqWQZjB8IExEABoiiUvWKClYy%2FndxOO2QOg79cqAERjyQt43P10W2eX6bYCFAAEAIB6rJz9hkGY0dBOgAIAUi%2BQxuD6exG%2FttVQASCcG4YAFuSll43BjMp0OwHeNfoCAEAtll%2FP8w2AciddDYCdAAUAmtM3BMBjN%2BFbId8C6DnyAoAAANRzYdMGeLbgYRdAAQCgExc2bYBnYhdAAYBmqXwFHg8AMdsA9xx5ASDaj14nQFiQpVe%2FahBmoA2wAADQjQtbhjUAEWf%2FhZboAkBgPUMAVMrtjyN%2BbY9CBQCAeuTaAyClwQNvAQgANM3yF9Rs6diXs%2Fx3Dzc%2FjHi4%2Bn6xAkBUVw0BUEnZBTDdRoBaoqe0Ygho9Af3n79bLL3xZnb%2F7sE%2F%2FU1R3vyFA5iB5TNfNwgzGu16BCAA0LR%2BuG987Hhx5Oz57P7ZS%2BN%2Ft0skizTceD%2Fi11YEmJBHAAJAs7ZuO%2BosOKzZCXCm2X%2FaTYDUQQkA0PIT5ezXDEImll%2F%2F%2FSz%2F3eXOp2n%2B7tDalgCAFYAmZhueo8NTDTfj7QSoDbAAENb4xx8uABT37znwLJQ2wDMGj4ExEACAZ99U3jpvEHK5qGkDPOMf95sRAEglVBXs6NplRxyeELQNcM%2BRFwCiUwWbwwrAS8cNQga0AZ6dNsACAPC8AJBh86KQxynTNsCjLTsBIgBEdCnaFx5d9xgAHjsnYm4FrBW6AACZzC5f%2B4pBaPsFbdUjgFkNPQIQAEgm3jLYTp6vAi69dsqvte3HKNMugBF7ABR2AhQAiNcLu7z5kaMO%2ByXqj1GmnfwLAAIAZDK7fF0hYNutnP2GQZiBXQAFANIKl4LLrU%2FyDAA2mWFBBtffi%2Fi17QQoAMQWsR1wuf2JA89ivCSkzbQCkHAnwPG1z2uAAgBksgKgHXDr5dgIqExYFFsO%2FWYEAFILtQpgR0DYdz7cCvkGQM%2BRFwAIGACKnc8cceq%2FmGW4CVBqw4EiQAEAePHJctYjgFYfn9fyDAAp2wCXdgIUAEguXDWsdsCwdy7EbAN8yZEXAHjoriHIxDG7Arb2YqYN8My0ARYAgIOeMHYFbK1c%2BzQEXQHwCqAAwJ5etC9cXvMIACbnwvbHEb%2B2JkACAGQ2y3zVjoBtpQ3wbCz%2FIwC0Q7jlsDLbHQEFAGq%2BEW9%2BGPFr9x15AYBi0hIz3o6Am5oBQcownHInwIgt0AUAyNzSG79nEFpq%2BczXDcIMRrvGQACgLUI9Bii3buf5D7cjIDUabrwf8WsrABQAiHxS5LolMO1kq%2BY5VgCGyZ4BeAVQAIAMTxjtgFtp%2BfXfzzMI73yaMAD43QgAtEU%2F2hcu7QpIcMPNkDsBagMsAPCEG%2BECwH27AlKPpVe%2FahBmXQGwE6AAYAhgxpPmLY8BWndMMt0KOGUbYDsBIgC0R7xeANoBE1zQNsA9R74dVgxBa6iMzSU1%2F9F%2Fejh7E2BaMfNfPvv1YuXctw3GDLQBRgCAOSyPA8DyNARc%2FtkkCIyuX1bU2NRFa3yzXxnf9JfPfKNYfj3vLYBHW3YCJJ0lQ9Aety6cCRXLq2fpR%2F%2FH33bnC%2B18VgzHgaCcBoIMeh28fGq5%2FYFrfJN%2FeNP%2FRue6%2FX36X%2F8g2QrAzq%2FSFAGsrm%2B471gBgI45dvzhysDe6kC1IlAFgYcrBB9MAgIHCIZ7y%2FpHxzf9apavyc8iAoAxQABom2pp7GSUL1t2%2FIa49MabxXL1%2BdM%2Fn%2FzvyarAOAxMVgk8LvjNOI1v8NWNfnLDH9%2F4c63on%2FkmHLMHQN8vXgDg6ao3AdbCBIBgN8FJF8HxZ%2FnP%2FstkNaBaFRh98H%2ByeVxQ64Vnbzm%2FWtrP%2FTn%2B3O6n2xK7TLcVoAAgAEBwx44XR85%2Fa%2FKZXJDHAWDyuGASCLr3uKC6yVez%2FGnxnmX9xKsPdgJEAGidcNWx1Y1v6bWvhD%2Fw1RgsV5%2F99QOXH4aBHF83rG7wk8K9qlI%2F0LL%2BLAbX34v4te0EKADwDFfHn7dDBYDt2wLA026g0%2FqBYt%2Fjgpa%2Fblgt66%2Bc%2B5NOvJ7X%2BfMu3U6Ad42%2BAAAc1DMeF0wLClM9Lpgu6x89%2F%2B3OvZ7XyE14J10NgJ0AEQDapx%2FuIljNZm2xO9vqwN7jgup1w5Xirx9%2F3bAKBAvyqOte9Sz%2F3Lc9xz%2FsTfhWyLcAeo68AIAA8JB34w8fCJ7yuuHog58d%2BnHB9PW8lb1Wu57jdyR42AUQAQC6qXrd8Mh0VWXG7oRd7rrXuhtxojbAdgFEAGincBWyVXHbpNCNxXiyO2FVP1C9XbDXnfDIq6881lvfsn6Dv%2F3tePsArK5v9Bx5AYCnnxx3bl04YyBYmEn9wJ%2F%2B%2BeRz9OjR4viJEwYlGG2AmTpiCADM%2FhtgF0ABgBfohboQZtjkBg6r3P444tfWBEgAACCVwQNvASAAtFW8ZTKvAhLMcPPDiF%2B778gLADzf1WhfeLRpa1xiSdkFMN1GgMUNR14AACBV4N71CAABoK1C7ggIkQw33o%2F4tRUBCgA4SZ6wddtRhyZm%2F2k3AfIaoAAAEFu582mavzu0%2FI8A0Gb9cLOSm4oAiWW4GW8nQG2ABQBefJKECwDF%2FXsOPDQRPAbGAAEAIImkbYDtBIgA0HqhCgG1AyaSoG2Ae468AMDBqJYFaqcNMAIAQCKjLTsBIgDwbJfCXRSvewxAkN96zK2ArzryAgAAiQw9AkAAoHV2vApIkJtwwB4AhZ0ABQAOrBftC5c3P3LUiSFR34sy7eRfABAAAEjBLoAIAHkIVzGrHTARlDv3isH19yJ%2BdTsBttCSIWinWxfOhIzrR85%2Fqzjy1vniyNnzxdIbb%2FohLNDRo0eLEydOGIgFq7b%2B3b38k%2FF%2F30v6%2FH%2F3fll8fjdNK8DV9Q33mhZaMQS0aiXg8s8mn0k6fe0rkyBw5GvfHP%2F3a0Vx7LgBov2%2F4e1fFoMrPxnP9N%2Bf3PTLlhS4lkPHBgEgF%2F3x53TkASi3PimG1efn%2F%2FowELzxZrFcrRCc%2F6bVAdrzOx3f4Ksb%2Fe74pj8c3%2FSDvuf%2FPJb%2FBQAEgENeaG%2F%2BohhUtQI%2F%2FvvJakC1KvBwdeD8ZLUAmlIt5Vez%2FGp5P5dn%2BsNBsqeKugAKAFCjnc8ef1zwxpsPHxdU9QPnv2V8qFU1q69m94PxTL%2B68ZcZ9q0o7QSIAJCNatlszTAcfHVgWH3%2B7V8m%2F3saBBQTMveMuSXFex1wyRAIAMzmriE4xIzt2uVH2wxPiwmXxqGgqiFQTMizZvnT4r3qv50LNNoAIwAQbnVgr5iw%2BPm%2FFoPifz4qJlzae92QoL8LxXtNUQMgADCj3vjzjmFYwIX%2FUTFhoZgwmByL9zrAWwACALTQk8WE1eOC899UTNgR0%2BK9ySy%2FRe%2FkNx58LP8jAMALVgeqxwX%2F9i%2BKCTO2vwmP4r1W6BuCdtKescWitgNu7cnSsWLCrrQCrm7y1c2%2Bq8V7tYSiL8ri%2Fq%2B1AcYKAMy%2FOqCYMP1xULw3s9GuMUAAyE1VPXvSMLT0RqSYsNFZ%2FmRpv7rpW9bPiQJAAYBDnDxrhiEDignrnbEq3qt3PIfaACMAQDOrA4oJZ7a%2FCY9l%2FboDgDFAAMhN3xB05AKsM%2BFveVS8d%2BXfvZPfXR4BCADM6YYh6OjqQMBiwmoZfzLLr17PU7zXbABNtxOgluYCAPDMG2OHiwmnHfcU7yX%2BjdkJEAEgO5bPosm8mFDxHk%2FoGQIBgPmooI0%2Bc2t5MeH0nXzFe%2B2lDTACAHRAG4oJFe9hEtMNWjS22K0LZ6omQL82EhzoZJ6xmPCgrYD3F%2B9V%2F7Wsn98KwM6vtAFGAMgxBFi%2FY3YHKCZ8XgCoivd2L%2F%2FEhjod8OCzsvjiMwGA3%2BYRAHTRjMWE1bP7%2FbvomeVTg74hEAA4nF6hHTCH9LRiwvIP%2FrD4%2FKWB4r2uH%2Fsy2SKiACAAAG1TFRI%2BqD6nlg1Gxw3tBMgzHDEEraeKFsiRPiYCAId01RAA8yqH2gAjAACEYydABIB89Q0BkCGPAAQABAAgyex%2FkLSNiPolAQCAFOwCiACQN8toQHZW1zd6RkEA4HAnkWU0YC7DB8YAAQCA5pi4CADUxGMAwDULAUCaBnixwQObiSIAANCcviEQAKjHJUMAHFT1%2Fv%2BDnTJlG%2BAbjkL72Q0QIHPVjr%2FDB2Ux%2BLyc%2FFf7XwSA7lADADymutFXr%2FntfjG%2B4e%2B27lm%2FIkABACcTUIdqVj%2BZ5X%2FxcJbf8i5%2FJi0CAADzmt7sq6V9y%2FoIADH1DQEEmOUPxjf7B8WjZ%2FkZs2qZgSVDkIdbF854oZfavXxq2SAkVBXvTW%2F2XSreW13fcG%2BxAgDAfi0v3kMAoIWqJbVzhgHyklnxXh16jroAQL1U1UIGpu%2FkK95DAADo%2Biy%2FO8V7JisCAC1UPQJYMwzQjln%2B9GZfLe0HWNafxVVDIABQr7uGANKZ3uyrmb7iPQQAgI6qnt1PC%2FeCFO%2FVpW8I8mA3wHz0DAEszmRZf3zD%2F%2BLeqPh%2F%2F3c4%2BXzx6Wiy1O%2FmLwBYAQDo0ixf8R4CABlQWQuHveEP972ip3hvUbQBzoR2jRnRDpi6RWgFrHivWdoAWwEASDbL37%2BLHiAAdEF%2F%2FDltGOA3pp33ps%2Fxdd5LyvK%2FAIAAAAuc5VfFe5%2BPZ%2FoPFO%2B1jFolAQCgxhu%2B4j0QAKwAQAyK97J0yRAIACzGDUNAl2f5ivegOV7XyMytC2feHv%2Fnj4uHGwOdMyIcRsrXABXvdUZvb%2Bb%2F7ur6hiJAAYCGwsDpvSDwZ3v%2FPWlUaHMAmBbv7Y5n%2Bpb1s9Xfu%2Bn%2FuPrv%2BKav8E8AoAWBoFoReHsvEFgdIHkAmBbvTZf2Fe9l6c4Ts%2Fy%2BIREAaHcYOPnE6sBpo0ITAeDRc3zFezm7Mp3lj2%2F4PcMhAJD%2F6kAVBP54b5UAagkA0w11FO9lP8t%2Fd98s37K%2BAECHA4FiQuYKAIr3OmMywy8ePsdXvCcAEDQMnC4UEwoAL5rlK97LXX%2FfLF%2FxHgIATw0E02LC6QoBwQKA4r1OULyHAMChwoBiwiABYH8THsv62VK8hwDAwgLB6X2rA4oJM%2FelLx959CyfLPWfmOVb1kcAoLFAsH91QDEhLN5khl8o3kMAoGWrA2v7VgcUE0I9s%2FxJ8d74hv%2Bu4UAAIIdAoJgQZnfniVl%2B35AgAJBzGFBMCM92Zd8Nv2c4EADociA4XSgmJK5%2BoXgPAQAUExJCr1C8hwAAL1wdWCsUE5K36Tv5ivcQAGDOQKCYkBwo3kMAgAWGAcWEtG2WX93w37WsjwAAzQaC04ViQprTf2KWr3gPAQBaEgj2rw4oJqQO%2B3fQM8tHAIBMVgfWCsWEzEbxHgIAdCwQKCbkaRTvIQBAoDCgmDC2yQy%2FULyHAADhA8HpQjFhl%2FULxXsgAMABAsH%2B1QHFhHl6d98sv284QACAeVYH1grFhG03Ld77sQ11QACARQQCxYTtcKd4%2FBU9s3wQAKCxMHDyidWB00ZloXqF4j0QAKCFgeD0E6sDHhccTr9QvAcCAGQYCKoQoJhwNor3QACAToWBk8XjrxpaHXhI8R4IABAqEJwrHm9GFMWdJ2b5lvVBAIDQqwNrRXeLCScz%2FMKGOiAAAM8NBKeLvIsJ%2B8Xjr%2BiZ5YMAAMwRCKoQ0OZiwumGOor3QAAAFhQG2lJMqHgPBAAgYSBoqphQ8R4IAECLVwfWivqKCScz%2FELxHggAQFaB4HQxWzFhfzrLH9%2Fw3zWCIAAA3QgEVQjYX0x454lZft8oQQz%2FX4ABAK6DJElxTemaAAAAAElFTkSuQmCC
or this:
<img src="islifethissimple.png" />
Remember that:
Javascript can be disabled.
Data urls may reduce 2 requests per image, but they are lengthy.
Data url images are not cached so the user would be requesting the full page each visit (entirely true?)
Need to make one small change in the image? You'll need a complete new data url. In an image sprite, all your images are used in one file and can be easily edited.
I would say that it's a bad idea as none of your images would show up if the user has JavaScript disabled. Yahoo! reckon that about 2% of their visitors don't use JavaScript (source)
Related
I'm creating a few pages in my app (currently running Angular on my front-end) that each contain a good deal of logos. I'm currently creating directives for each SVG logo (putting the inline SVG code in a template), which makes the code a lot more readable, but due to the number of logos, I'm starting to wonder if it would make more sense to create a CSS sprite instead.
I would appreciate some thoughts from a performance perspective on this. I know CSS background images get cached, so that's a plus. SVG offers me more flexibility if I want to, say, color or size some specific logos differently, but if it's costing me a fair amount in terms of loading time I'd rather opt for the background image.
I'm doing something like this for the company I work for. They have hundreds of images that could easily compress into one SVG sprite. I guess the answer depends on the project, will it get bigger? if yes I think taking the time to implement the sprite sheet now would be a great idea, also you could use it for icons. here is a great article on CSS tricks.
If you will start doing that I recommend using Grunt and implement grunt-svgstore it saves a ton of time creating the sprite sheet for you and it's pretty simple to implement, something like this.
grunt.initConfig({
svgstore: {
options: {
option like prefix ID with 'icon', indentation, etc.
}
},
default : {
files: {
'dest/dest.svg': ['svgs/*.svg'], //destination, files to convert
},
},
},
});
TL;DR: From a coding perspective I would say keep things simple, from a UX / UI perspective it depends on your use case.
I would go with the background image unless the interaction with the logos is a key element of the user journey.
If for instance it is there to show the number of clients, their high profile or your status as a result, then an image is fine. You won't be changing it that often and it's not necessary to set up the situation so you can manipulate the logos too much.
If you've got an integral interaction that is using the logos, a user hovers the logo changes colour and then on-click expands and shows more information - then the SVG route makes sense and is probably worth the effort.
Keep things user centric - Is the cost in time to you going to gain enough of a user benefit?
I have a website which contains some images in index.php
The problem I am facing is the whole page is not loading at once, I think images are taking some time to load
So what I have done is, I am showing an loading image at first and then after some time I am showing the page, that resolves the problem. But I am curious to know is there any other better way to do this?
I prefer to optimise the hell out of my images.
PNG images
You can use pngcrush to optimise your PNG files for you, but personally I find that once I'm done with it pngcrush only succeeds in making it bigger.
Use Indexed-PNG wherever possible. This will limit you to 256 colours, and most graphics editors won't allow partial transparency in Indexed-PNG (but it is possible - you just need the right editor. I use a custom PHP script with the GD image library) but you can expect to drop file size down to just a tiny fraction of what it was.
Reduce the amount of colours overall. PNG compression works best with blocks of the same colour, so reducing the number of colours improves compression.
GIF images
Especially for animations, there's a lot of things you can do.
Reduce the number of frames. Avoid duplicate frames at all costs, and just set the previous frame to have a longer display time.
Use combine rather than replace if possible. You will again have problems with transparent areas, but by using combine you can have each subsequent frame only change the stuff that... changes. This avoids the redundancy of re-writing the entire image if only a small part changes. GIMP has a useful filter "Animation > Optimize for GIF" which will do this for you.
Reduce colours as much as possible. GIF is limited to 256 colours, but if you can limit yourself to 32 or so, you'll get a much smaller file.
Using the above techniques, I once managed to shove 8MB of raw image data into a 125kb animated GIF.
JPG images
JPG is great for photos, but cameras have a tendency to write MASSIVE files.
Play around with the compression factor. Start at around 40%, and slowly bring it up until it looks acceptable. GIMP will show you a preview and the resulting filesize, so make use of that to find an acceptable compromise.
Scale the image down. You don't need 9 megapixels or however massive resolution cameras take now...
The above should help you reduce the amount of size taken by your images. Obviously, you should also cache images appropriately, so they only need to be retrieved once. Also make sure that you specify width and height on image elements so that the browser can reserve the space for them and avoid jumping around as they load...
And you should be pretty good.
It's hard to say what other options are available without knowing what the page looks like, but one option is to reserve space for the images so that the page text renders quickly in the correct position, and the images then load later.
Does anyone know why Javascript performance would be affected by the loading of lots of external JPG/PNG images into HTML5 Image() objects, totalling approx 200Mb-250Mb. Performance also seems to be affected by cache. Ie. if the cache is full(-ish) from previous browsing the performance on the current site is greatly reduced.
There are 2 says i can crudely solve it.
clear cache manually.
minimise browser, wait about 20 secs and re-open the browser after which time the iOS/browser has reclaimed the memory and runs the JS as it should.
I would have expected the iOS to reclaim required memory to run the current task, but it seems not. Another workaround is to load 200Mb of 'cache clearing' images into Image() objects, then remove these by setting the src = "". This does seem to help, but its not an elegant solution...
please help?
First and foremost read the excellent post on LinkedIn Engineering blog. Read it carefully and check if there are some optimizations that you can also try in your application. If you tried all of them and that still haven't solved your performance issues read on.
I assume that you have some image gallery or magazine-style content area on your page
How about having this image area in a separate iframe? What you could do then is this:
Have two iframes. Only one should be visible and active in time.
Load images into first iframe. Track the size of loaded images. If exact size tracking is hard
numberOfLoadedImages * averageImageSize
might be a pretty good aproximation.
As that number approaches some thresshold start preloading the currently visible content into second iframe.
Flip the visibility of iframes so the second one becomes active.
Clear the inner content of the first frame.
Repeat the whole procedure as necessary.
I don't know for sure if this would work for you but I hope that WebKit engine on iPad clears the memory of frames independently.
EDIT: It turned out you're writing a game.
If it's a game I assume that you want to have many game objects on the screen at the same time and you won't be able to simply unload some parts of them. Here are some suggestions for that case:
Don't use DOM for games: it's too memory-heavy. Fortunately, you're using canvas already.
Sprite your images. Image sprites not only help reducing the number of requests. They also let you reduce the number of Image objects and keep the per-file overhead lower. Read about using sprites for canvas animations on IE blog.
Optimize your images. There are several file size optimizers for images. SmushIt is one of them. Try it for your images. Pay attention to other techniques discussed in this great series by Stoyan Stefanov at YUI blog.
Try vector graphics. SVG is awesome and canvg can draw it on top of canvas.
Try simplifying your game world. Maybe some background objects don't need to be that detailed. Or maybe you can get away with fewer sprites for them. Or you can use image filters and masks for different objects of the same group. Like Dave Newton said iPad is a very constrained device and chances are you can get away with a relatively low-quality sprites.
These were all suggestions related to reduction of data you have to load. Some other suggestions that might work for you.
Preload images that you will need and unload images that you no longer need. If your game has "levels" or "missions" load sprites needed only for current one.
Try loading "popular" images first and download the remaining once in background. You can use separate <iframe> for that so your main game loop won't be interrupted by downloads. You can also use cross-frame messaging in order to coordinate your downloader frame.
You can store the very most popular images in localStorage, Application Cache and WebSQL. They can provide you with 5 mb of storage each. That's 15 megs of persistent cache for you. Note that you can use typed arrays for localStorage and WebSQL. Also keep in mind that Application Cache is quite hard to work with.
Try to package your game as a PhoneGap application. This way you can save your users from downloading a huge amount of data before playing the game. 200 megs as a single download just to open a page is way too much. Most people won't even bother to wait for that.
Other than that your initial suggestion to override cache with your images is actually valid. Just don't do it straight away. Explore the possibilities to reduce the download size for your game instead.
I managed to reduce the impact by setting all the images that aren't currently in the viewport to display:none. This was with background images though and I haven't tested over 100Mb of images, so can't say whether this truly helps. But definitely worth of trying.
I am learning to develop mobile applications, quite in the initial phase.
This query is not related to mobile but more to html/css/js.(for
I intend to make a simple game, where a picture is seen, a few options are available and the user can drag and drop these options onto the image.
eg. There is an image of a plant > options are #leaf #stem #flower #bud
The user must drag and drop the correct option to the correct place on the image to get points. i.e Drag the #leaf option onto the leaf of the plant.
Now my problem is the image, the separation of these points, I can't figure out how to do it.
Query in short: How do I access separate points/sections on a single image in html/js for above purpose?
Query (longer version)
I did a little search and realised I can slice the image and recreate it using multiple images, I tried this, it sort of works but it has a a lot of drawbacks:
1)More images mean more space, combined size of the split images was about 1.5x the original image(this is just splitting it into 4 images)
2)For a complex picture, the number of images to slice into is large and hard to manage in css(n00b==me) as they don't just need to be split into a simple X*Y grid but a much more complex split depending on the object in the image.(realised when I was trying to do a simple cell structure img)
3)More images also means more http requests(in case the app is WebView based) which will increase loading time.
It just seemed liked too much of a hassle, there must be a better way.
Then I saw css sprites , I dont need to combine my images like sprites are intended for, rather the reverse. Just access parts of my pre-existing image, as separate objects.I haven't tried this(working on it) and and I haven't seen this being done either, or maybe its being done and I'm not seeing.
Please help guys, my problem is quite simple(I think) , I think I'm just not getting the correct google search terms.
If anybody has any ideas,links, resources and also any clarifications as I may not have put up my problem as clearly as I'd like to, please do reply.
regards,
Rahul Agarwal
You could try to place transparent divs over the main image using absolute position and fixed dimensions. Those divs will be assosiated to the possible options, and when a user drops an option over some specific div, you'll know what points to give.
Little demo using two divs and an animated scaling to show that the positioned divs will scale according to their parent:
http://jsfiddle.net/VK3A8/
fiddel with image:
http://jsfiddle.net/8qLFc/4/
I need to dynamically load and put on screen huge number of images — it can be something like 1000–3000. Usually these pictures are of different size, and I'm getting their URLs from user. So, some of these pictures can be 1024x800 or 10x40 pixels.
I wrote a good JS script showing them nicely on one page (ala Google Images Search style), but they are still very heavy on RAM used (a hundred 500K images on one page is not good), so I thought about the option of really resizing images. Like making an image that’s 1000x800 pixels something like 100x80, and then forget (free the ram) of the original one.
Can this be done using JavaScript (without server side processing)?
I would suggest a different approach: Use pagination.
Display, say, 15 images. Then the user click on 'next page' and the next page is shown.
Or, even better, you can script that when the user reaches the end of the page the next page is automatically loaded.
If such thing is not what you want to do. Maybe you want to do a collage of images, then maybe you can check CSS3 transforms. I think they should be fast.
What you want to do is to take some pressure from the client so that it can handle all the images. Letting it resize all the images (JavaScript is client side) will do exactly the opposite because actually resizing an image is usually way more expensive than just displaying it (and not possible with browser JS anyway).
Usually there is always a better solution than displaying that many items at once. One would be dynamic loading e.g. when a user scrolls down the page (like the new Facebook profiles do) or using pagination. I can't imagine that all 1k - 3k images will be visible all at once.
There is no native JS way of doing this. You may be able to hack something using Flash but you really should resize the images on the server because:
You will save on bandwidth transferring those large 500K images to the client.
The client will be able to cache those images.
You'll get a faster loading page.
You'll be able to fit a lot more thumbnail images in memory and therefore will require less pagination.
more...
I'm (pretty) sure it can be done in browsers that support canvas. If this is a path you would like to take you should start here.
I see to possible problems with the canvas approach:
It will probably take a really long time (relatively speaking) to resize many images. Because of this, you're probably going to have to look into utilizing webworkers.
Will the browser actually free up any memory if you remove the image from the DOM and/or delete/null all references to those images? I don't know.
And some pretty pictures of a canvas-resized image:
this answer needs a ninja:--> Qk