Friday, 25 August 2023

A Comparison Between Tables and Divs (Part 2/2)

Divs have been the de facto standard for web layout for over a decade since the advent of CSS. The versatility of divs cannot be overstated, though it is possible (and alarmingly easy!) to overuse them.

Deep levels of nesting.

Any web developer who has ever run into front-end maintenance problems due to multiple levels of nested div tags, will know exactly what I mean. This, of course, naturally leads to the question: Can tables be nested too? The answer is yes, and those seriously disturbed individuals who have attempted this will doubtless live to regret such depravity.

Learning curve

Divs are usually used as containers for HTML elements and content (including other divs) and then styled using CSS. This can lead to a whole ton of nested divs if a web developer is not careful. Again, as with tables, any missing open or closing tags leads to malformed HTML, thus it is important to keep them as simple as possible. Unlike tables, this is actually possible for divs, since the minimum viable HTML for one div is a single div tag.

<div>Content</div>

The learning curve for divs by themselves isn't huge, though CSS is another matter entirely. There are tons of options that can drastically change the visuals of your site. In addition to learning about the CSS Box Model, a web developer also needs to understand the position property if fancier shenanigans are required.

Use cases

Web layout now predominantly uses divs for many reasons, chief of which is mobile layout. Div layouts are easily made to be scalable (due to CSS) and this a site can be easily fitted to whichever screen size is required, without needing to make a lot of changes.

Different devices and
screen sizes.

Divs can also be used for tabular layout with a few interesting options depending on the library used, but this also tends to complicate matters; and in my opinion, does not significantly have less problems than simply using table tags for such use cases.

SEO

The ability to separate styling from content is one of the greatest boons of div tags and CSS. This solves many problems that table-based layouts are prone to.

Crawling the web.

For example, when using div tags for layout, it is possible to position important content in the HTML for web crawlers to pick up first, while visually repositioning the content elsewhere or even hiding it. Not only is it possible, CSS makes it almost ridiculously easy.

Conclusion

Tables and divs both have their place. Divs are ubiquitious. Tables fulfill a smaller, but still vital, place in the HTML ecosystem. It is important to use both for their respective best use cases.

Your div-ine web developer,
T___T

Wednesday, 23 August 2023

A Comparison Between Tables and Divs (Part 1/2)

With the birth of the Internet, there have been two HTML elements that have often been used to do the same job - namely, the table and div tag. In this blogpost, we will compare the two and their best use cases.

Tables are predominantly a grid-layout element that is best used to present data that can be presented in a spreadsheet. In fact, if you highlight a HTML table and copy it, you can then paste the table in a spreadsheet application.

Spreadsheet data.

Tables can have columns that span multiple rows, and rows that span multiple columns. In this manner, more complex data can be represented.

Learning curve

Tables are not a difficult concept to muster. They can, however, be heinously cumbersome to write, let alone maintain. The table tag does not function on its own; it at the very least requires tr and td elements. thead and tbody are largely optional.

<table>
    <tr>
        <td>Content</td>
        <td>Content</td>
        <td>Content</td>
        <td>Content</td>
    </tr>
</table>


Usage is simple enough even if one throws rowspan and colspan attributes into the mix. Enough repetition and a child could learn it. The real question is whether or not that child would want to.

The problem with too many tags is that if one closing or opening tag is left out, this leads to malformed HTML. And with the nature of tables, this happens all too easily.

Use cases

These days it's not even a contest, but there was a time when using tables for page layout was actually a thing. In some dark corners of the web, table-based layout, along with (gasp!) frames, can be found if one looks hard enough. These days, though, suggesting tables as a site layout would earn you some serious side-eye.

Tables were adequate for layout back when screen sizes did not vary so much. Fixed width-layouts could handily be created with table elements that had the border attribute set to 0. Still not ideal, and smacked of trying to fit a square peg in a round hole, but they worked in a pinch if you weren't planning to make frequent changes or do anything extremely fancy.

You're not fitting that in.

Times have changed, and table layouts for websites are almost completely a thing of the past. Yes, I said almost. Hey, some people enjoy suffering; there's no accounting for taste, is there?

No, tables have now been relegated to carrying out the task they were originally meant for - presenting grid data. And that's a task they perform like no other.

SEO

Now, web crawlers have no problem reading content from tables. However, since tables and content are intrinsically tied together and tabular data is read linearly, this presents a problem if the visual design of the site clashes with the SEO requirements.

For instance, say you have content that you want displayed at the top of a site. However, in terms of importance, some other information takes precedence and you want the web crawlers to read that first. That can't happen in a table element unless you replicate the information at the top of the table and then hide it visually (which is workable I guess, just a huge pain in the butt to maintain).

Less than ideal
for the blind.

Also because tabular data is linear in nature, content readers for the visually impaired would totally mess it up if they were reading table-based web layout.

Next

We examine the div tag.

Saturday, 19 August 2023

The How And Why Of One-Hot Encoding

Categorical data in a dataset are labels, usually in the form of strings. As I've mentioned before in a previous blogpost, they can also be numbers, but even if that were the case, they are numbers with no numerical relation to each other.

This normally does not present a problem; however, when categorical data needs to be input into a Machine Learning model, they need to be converted into numeric data.

Can't ingest letters...

The reason for this is that Machine Learning models currently do not work very well, or at all, with non-numeric data. To these models, the numbers need to have some sort of numerical relation to each other (as in the case with quantities, dates and such), or consist of 1s or 0s. When using such Machine Learning models, One-Hot Encoding (OHE) can be a boon as it allows you to have categorical data in your dataset.

How it works

Let's first use a sample column called Gender. Here's the column and its data.

Gender
M
M
F
M
M
F
F


For categorical data, we split that particular column into a number of columns equal to the number of possible values for that column. Thus, for a column like Gender, you might have two columns. Unless, of course, it's somewhere like Canada, in which case you might have more. Don't ask me why; it's how the world rolls right now.

The columns are renamed according to their data value and the original name, so we might have Gender_M and Gender_F. We sort the new columns alphabetically, so Gender_F comes before Gender_M. And then we convert the data into 1s and 0s. 1 being true and 0 being false. Thus, if the data is "M", it will show up as 1 under Gender_M and 0 under Gender_F.

Gender_F Gender_M
0 1
0 1
1 0
0 1
0 1
1 0
1 0


For a column with even more possible values, let's think of something like Shirt_Size. We'll place it next to the previously converted values for better clarity.
Gender_F Gender_M Shirt_Size
0 1 L
0 1 L
1 0 M
0 1 S
0 1 XL
1 0 L
1 0 XS


Here is the conversion.
Gender_F Gender_M Shirt_Size_L Shirt_Size_M Shirt_Size_S Shirt_Size_XL Shirt_Size_XS
0 1
1
0
0 0 0
0 1 1
0
0 0 0
1 0 0 1
0
0 0
0 1 0 0 1
0
0
0 1 0
0 0 1
0
1 0 1
0
0 0 0
1 0 0 0 0 0 1


Why not One-hot Encoding

Yes, OHE, like all solutions, is not ideal for every situation. These are some of the less desirable outcomes it can produce.

If there are many possible values for a column (such as a color code), this can lead to an unreasonably large number of columns. Basically, too many predictors (or data points) in the dataset.

Too many columns.

And if among these generated columns, only one column is a 1 while the others are 0, this leads to sparse data.

All this can lead to increased difficulty in training the Data Learning model.

Another issue, related to the previous points, is that OHE produces additional columns (and thus increased space) without actually adding to the value of the data. The data still means the same thing; it only takes up more space now. Kind of like if instead of this nice, short, to-the-point blogpost, I encapsulated the same points in a five-page article.

Conclusion

OHE is not the only method of preparing data for a Machine Learning model. There are others, of course, and perhaps on another occasion I can present them. Till then...

Have a One-derful day,
T___T

Monday, 14 August 2023

Web Tutorial: The Chameleon Site

In recent weeks, I came across this amusing story about eBay. Basically, it's about UI and UX, and how users react negatively to sudden changes in a system unless that change takes place very slowly, over time. In the story, such a change was brought about, to the site's background color.

This story amused me so much that I just had to write a bit of code to replicate this effect. It's not spectacular and accomplishes nothing really new, but let's dive into it anyway, eh?

We first have some standard website HTML. I generated the text using ChatGPT.
<!DOCTYPE html>
<html>
    <head>
        <title>Chameleon</title>

        <script>

        </script>
    </head>

    <body>
        <p>
            Welcome to ColorShift! We are passionate about the power of colors to transform and enhance your world. Whether you're looking to revamp your home decor, design a striking logo, or simply add a touch of vibrancy to your digital creations, we have you covered. Our expert team is dedicated to helping you explore the endless possibilities of color.
        </p>

        <p>
            Discover a kaleidoscope of hues, shades, and tones that will ignite your creativity. Dive into our extensive color palette and find the perfect combination that speaks to your unique style. From bold and energetic to calm and soothing, we offer a vast spectrum of options to suit any mood or aesthetic.
        </p>

        <p>
            Our intuitive color selection tool allows you to experiment with different combinations, ensuring you find the harmony you're seeking. Adjust brightness, saturation, and contrast to achieve just the right balance. Create stunning gradients or play with complementary and contrasting colors to make your designs truly stand out.
        </p>

        <p>
            Whether you're a seasoned designer or a novice enthusiast, our blog is a treasure trove of inspiration and guidance. Dive into articles that delve into the psychology of color, explore the latest trends, and learn invaluable tips and tricks to make your colors pop.
        </p>

        <p>
            At ColorShift, we understand that colors have the power to evoke emotions, convey messages, and make a lasting impression. Let us be your guide on this chromatic journey. Unleash your imagination, unleash the colors!
        </p>
    </body>
</html>


Within the script tag, we create the setBgColor() function. It has three parameters. The first is maxDays, which is an integer that specifies how many days the change is going to take place over. fromColor and toColor are objects that dictate the beginning color and the end state color, each of these containing the RGB values in integers, as properties.
<script>
      function setBgColor(maxDays, fromColor, toColor)
      {

      }

</script>


When the site loads, we want to run the function. Let's first set it at 100 days, from the color white to orange.
<body onload="setBgColor(100, {r:255, g:255, b:255}, {r:255, g:200, b:0})">


Back to the setBgColor() function, we begin by declaring body as the HTML body tag.
function setBgColor(maxDays, fromColor, toColor)
{
      var body = document.getElementsByTagName("body");
      body = body[0];

}


We then declare startDate as a new Date object, and as a test, set it to the first day of this year. For this code to work, startDate should be before today's date.
function setBgColor(maxDays, fromColor, toColor)
{
      var body = document.getElementsByTagName("body");
      body = body[0];

      var startDate = new Date();
      startDate.setFullYear(2023, 0, 1);

}


Now we declare currentDate as another Date object, and it's today's date. Next, we have ms, which we use to calculate the number of milliseconds between currentDate and startDate.
function setBgColor(maxDays, fromColor, toColor)
{
      var body = document.getElementsByTagName("body");
      body = body[0];

      var startDate = new Date();
      startDate.setFullYear(2023, 0, 1);

      var currentDate = new Date();
      var ms = currentDate.getTime() - startDate.getTime();

}


And then we do some math on ms to get the number of days, assigning it to the variable days. We use floor() because days might not be a whole number, and it would be easier if it was.
function setBgColor(maxDays, fromColor, toColor)
{
      var body = document.getElementsByTagName("body");
      body = body[0];

      var startDate = new Date();
      startDate.setFullYear(2023, 0, 1);

      var currentDate = new Date();
      var ms = currentDate.getTime() - startDate.getTime();
      var days = Math.floor(ms / 86400000);
}


We declare finalColor and set it to the value of toColor.
function setBgColor(maxDays, fromColor, toColor)
{
    var body = document.getElementsByTagName("body");
    body = body[0];

    var startDate = new Date();
    startDate.setFullYear(2023, 0, 1);

    var currentDate = new Date();
    var ms = currentDate.getTime() - startDate.getTime();
    var days = Math.floor(ms / 86400000);

    var finalColor = toColor;
}


And now we set the background color of body to use the r, g and b properties in finalColor.
function setBgColor(maxDays, fromColor, toColor)
{
    var body = document.getElementsByTagName("body");
    body = body[0];

    var startDate = new Date();
    startDate.setFullYear(2023, 0, 1);

    var currentDate = new Date();
    var ms = currentDate.getTime() - startDate.getTime();
    var days = Math.floor(ms / 86400000);

    var finalColor = toColor;

    body.style.backgroundColor = "rgb(" + finalColor.r + ", " + finalColor.g + ", " + finalColor.b + ")";
}


What do we do with days, then? Well, we use a conditional statement to check if days is less than maxDays. If so, we'll alter the value of finalColor (not right now, though) but if not, the background color of body will effectively be the current value of finalColor, which is toColor.
function setBgColor(maxDays, fromColor, toColor)
{
    var body = document.getElementsByTagName("body");
    body = body[0];

    var startDate = new Date();
    startDate.setFullYear(2023, 0, 1);

    var currentDate = new Date();
    var ms = currentDate.getTime() - startDate.getTime();
    var days = Math.floor(ms / 86400000);

    var finalColor = toColor;

    if (days < maxDays)
    {

    }


    body.style.backgroundColor = "rgb(" + finalColor.r + ", " + finalColor.g + ", " + finalColor.b + ")";
}


Since it's 3rd August and definitely more than 100 days (the value of maxDays), you can see the color of background is orange!




Now in the If block, declare ratio. It's the result of dividing days by maxDays, which will give you a value less than 1 because days is less than maxDays.
if (days < maxDays)
{
    var ratio = days / maxDays;
}


Next, we declare rDiff, which is the difference between the r property of toColor and the r property of fromColor.
if (days < maxDays)
{
    var ratio = days / maxDays;

    var rDiff = toColor.r - fromColor.r;
}


Same for gDiff and bDiff.
if (days < maxDays)
{
    var ratio = days / maxDays;

    var rDiff = toColor.r - fromColor.r;
    var gDiff = toColor.g - fromColor.g;
    var bDiff = toColor.b - fromColor.b;  
 
}


If rDiff is greater than 0 (which means there is a difference), we alter the r property of finalColor to be the r property of fromColor, plus the ratio-ed value of rDiff! So the closer days is to maxDays, the closer the r property of finalColor will be to the r property of toColor.
if (days < maxDays)
{
    var ratio = days / maxDays;

    var rDiff = toColor.r - fromColor.r;
    var gDiff = toColor.g - fromColor.g;
    var bDiff = toColor.b - fromColor.b;    

    if (rDiff != 0) finalColor.r = fromColor.r + (Math.floor(rDiff * ratio));
}


Yes, we can do the same for the g and b properties of finalColor.
if (days < maxDays)
{
    var ratio = days / maxDays;

    var rDiff = toColor.r - fromColor.r;
    var gDiff = toColor.g - fromColor.g;
    var bDiff = toColor.b - fromColor.b;    

    if (rDiff != 0) finalColor.r = fromColor.r + (Math.floor(rDiff * ratio));
    if (gDiff != 0) finalColor.g = fromColor.g + (Math.floor(gDiff * ratio));
    if (bDiff != 0) finalColor.b = fromColor.b + (Math.floor(bDiff * ratio));

}


Let's test this! Change the value here to an entire year.
<body onload="setBgColor(365, {r:255, g:255, b:255}, {r:255, g:200, b:0})">


It's now 3rd August. That's 212 days after 1st Jan, right? 212 over 365 is 0.5808219178082191, give or take. So the color should be 58% orange!




Change this to an even bigger number...
<body onload="setBgColor(3650, {r:255, g:255, b:255}, {r:255, g:200, b:0})">


And you see the color gets closer to the "original" color, white.




Conclusion

I hope the logic was clear. This web tutorial is a little light on functionality, but it was fun to do. Which is the reason why I do anything on this blog.

Don't fade away on me now!
T___T

Tuesday, 8 August 2023

From Twitter To X?

It appears that Elon Musk has come up with yet another bizarre decision. Sometime last week, Twitter underwent a name and logo change. Now, name changes aren't anything new in the world we inhabit. Facebook became Meta. Bruce Jenner became Caitlyn Jenner. In 1993, Prince became... well, you get the idea. Nothing to blink at.

Bye bye, birdy.

What's surprising, at least to me, is the what. From an internationally known moniker, the app has changed to a relatively generic X. The cute and tasteful blue bird that has served as the app's logo for more than a decade, is now a stylized and, dare I say, uninteresting "X". Now, not being a tech billionaire and all, nobody really cares about my opinion, and nor should they. I assume Elon Musk knows what he's doing... because I really don't. And I'm not entirely sure anyone else does either. Of all changes to take place, this stands out as a strange choice.

They call it a rebranding, but it really feels more like a debranding.

While I've never been a Twitter user, Twitter was such a mainstay of cyberspace that it was impossible for it to not be on my radar in some fashion. That's how strong its branding was. To throw that all away for a new but not altogether exciting image, seems counter-intuitive.

Burning questions!

Elon Musk has stated his desire to evolve Twitter into some kind of "Everthing App", just like WeChat. Something like that would require strong brand recognition as a foundation. Unfortunately, we live in a world where many things already share the name "X". And some of these things are distinctively pornographic in nature. Is that the kind of recognition that Elon Musk is going for? Somehow I doubt it.

Twitter's presence in not just cyberspace, but also Internet culture at large, has resulted in certain words being added to the lexicon. "Tweeting" is a verb which essentially means posting a message on Twitter. Now with the name change, what other changes could we see? Will Tweeting now be known as X-ing? Sounds uncomfortably violent.

Let me just do some X-ing...

Finally, of all the icons that Elon Musk could have gone with, why this one? I called it "relatively generic" earlier. I was being kind. It's boring. It's tepid. It says nothing about what the platform does. This could be deliberate. Musk could have some big plans for the app, and perhaps this generic quality is meant to avoid painting the app into a corner.

In Conclusion

With Meta's Threads encountering a bit of a downturn in recent weeks, this looked like a good time for Twitter to recover. Looks like it's not to be.

Still, it's going to be interesting seeing the two platforms taking turns to flounder. Definitely way more interesting than seeing one platform dominate. Let's hope that this does not lead to Elon Musk going from X owner to ex-owner. (hur hur)

Kick some X, Elon Musk!
T___T