Ads
Wednesday, June 30, 2021
Isolated Thunderstorms today!
With a high of F and a low of 59F. Currently, it's 66F and Fair outside.
Current wind speeds: 8 from the Southeast
Pollen: 6
Sunrise: June 30, 2021 at 05:28PM
Sunset: July 1, 2021 at 08:21AM
UV index: 0
Humidity: 71%
via https://ift.tt/2livfew
July 1, 2021 at 09:59AM
Dispense with the chasm? No way!
Jeff Bussgang, a co-founder and general partner at Flybridge Capital, recently wrote an Extra Crunch guest post that argued it is time for a refresh when it comes to the technology adoption life cycle and the chasm. His argument went as follows:
- VCs in recent years have drastically underestimated the size of SAMs (serviceable addressable markets) for their startup investments because they were “trained to think only a portion of the SAM is obtainable within any reasonable window of time because of the chasm.”
- The chasm is no longer the barrier it once was because businesses have finally understood that software is eating the world.
- As a result, the early majority has joined up with the innovators and early adopters to create an expanded early market. Effectively, they have defected from the mainstream market to cross the chasm in the other direction, leaving only the late majority and the laggards on the other side.
- That is why we now are seeing multiple instances of very large high-growth markets that appear to have no limit to their upside. There is no chasm to cross until much later in the life cycle, and it isn’t worth much effort to cross it then.
Now, I agree with Jeff that we are seeing remarkable growth in technology adoption at levels that would have astonished investors from prior decades. In particular, I agree with him when he says:
The pandemic helped accelerate a global appreciation that digital innovation was no longer a luxury but a necessity. As such, companies could no longer wait around for new innovations to cross the chasm. Instead, everyone had to embrace change or be exposed to an existential competitive disadvantage.
But this is crossing the chasm! Pragmatic customers are being forced to adopt because they are under duress. It is not that they buy into the vision of software eating the world. It is because their very own lunches are being eaten. The pandemic created a flotilla of chasm-crossings because it unleashed a very real set of existential threats.
The key here is to understand the difference between two buying decision processes, one governed by visionaries and technology enthusiasts (the early adopters and innovators), the other by pragmatists (the early majority).
The key here is to understand the difference between two buying decision processes, one governed by visionaries and technology enthusiasts (the early adopters and innovators), the other by pragmatists (the early majority). The early group makes their decisions based on their own analyses. They do not look to others for corroborative support. Pragmatists do. Indeed, word-of-mouth endorsements are by far the most impactful input not only about what to buy and when but also from whom.
from Amazon – TechCrunch https://ift.tt/3qCBo29
via IFTTT
How do you make a layout with pictures down one side of a page matched up with paragraphs on the other side?
I got this exact question in an email the other day, and I thought it would make a nice blog post because of how wonderfully satisfying this is to do in CSS these days. Plus we can sprinkle in polish to it as we go.
HTML-wise, I’m thinking image, text, image, text, etc.
<img src="..." alt="..." height="" width="" />
<p>Text text text...</p>
<img src="..." alt="..." height="" width="" />
<p>Text text text...</p>
<img src="..." alt="..." height="" width="" />
<p>Text text text...</p>
If that was our entire body in an HTML document, the answer to the question in the blog post title is literally two lines of CSS:
body {
display: grid;
grid-template-columns: min-content 1fr;
}
It’s going to look something like this…
So cool. Thanks CSS. But let’s clean it up. Let’s make sure there is a gap, set the default type, and reign in the layout.
body {
display: grid;
padding: 2rem;
grid-template-columns: 300px 1fr;
gap: 1rem;
align-items: center;
max-width: 800px;
margin: 0 auto;
font: 500 100%/1.5 system-ui;
}
img {
max-width: 100%;
height: auto;
}
I mean… ship it, right? Close, but maybe we can just add a quick mobile style.
@media (max-width: 650px) {
body {
display: block;
font-size: 80%;
}
p {
position: relative;
margin: -3rem 0 2rem 1rem;
padding: 1rem;
background: rgba(white, 0.8);
}
}
OK, NOW ship it!
The post How do you make a layout with pictures down one side of a page matched up with paragraphs on the other side? appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.
from CSS-Tricks https://ift.tt/3Ae73eM
via IFTTT
Amazon betrays its fear with petition to sideline FTC Chair and antitrust hawk Lina Khan
Amazon has petitioned that the newly minted Chair of the FTC and implacable critic of the company, Lina Khan, be recused from decisions relating to the company. The company argues that she has been too outspoken about the failure to regulate Amazon to handle matters impartially.
It will be for the FTC to decide, and its oversight committee to supervise, whether Khan will recuse herself; an agency spokesperson declined to comment on the matter.
Amazon’s argument (which you can read below) is that Khan has simply gone too far in her criticism of Amazon prior to her confirmation at the FTC, creating an effective “prejudgment” that precludes her ability to consider cases relating to the company objectively.
Although Amazon profoundly disagrees with Chair Khan’s conclusions about the company, it does not dispute her right to have spoken provocatively and at great length about it in her prior roles. But given her long track record of detailed pronouncements about Amazon, and her repeated proclamations that Amazon has violated the antitrust laws, a reasonable observer would conclude that she no longer can consider the company’s antitrust defenses with an open mind.
But it’s equally plain to “a reasonable observer” that Amazon, one of the largest and most powerful companies in the world, is a natural target for analysis by an expert whose professional opinion is that antitrust regulation is inadequate and dated.
And it was arguably this very idea that set her on the path to her nomination and sudden ascendance to Chair. Her “Amazon’s Antitrust Paradox” paper was not the manifestation of a vendetta against the online services giant — it was an indictment of the aging antitrust doctrine that permitted what she argued amounted to legalized monopolistic behavior.
Amazon may have been the one in the crosshairs, but it was only a stand-in for an entire school of regulatory thought that, Khan has persuasively argued in numerous papers and articles, mindlessly pursued a narrow definition of consumer harms and benefits. There are other ways that a company might act against consumer interests, such as crushing competition in a market by subsidizing costs through dominance of another market — something Amazon has made core to its entire business model.
Furthermore, the position of Chair at the FTC is one of leadership and priority setting, not utter impartiality. The impartiality comes in the form of legal arguments that show a company has, for example, broken the law. Long-held opinions count for nothing with a judge, including Khan’s own public and professionally expressed opinions; should she lead the agency in an effort against Amazon, she will have to support her interpretation of the law with facts and systematic argument.
While one can only speculate at the administration’s true reasoning for its rapid elevation of Khan, it’s hard to imagine that it’s anything but a whole-hearted endorsement of the philosophy and change she advocates.
Khan’s expertise and perspective on antitrust have made Amazon a natural antagonist, not because Khan is a monomaniacal crusader, but because Amazon could very well represent one of the largest regulatory failures in history. To point that out is not grounds for recusal — it may however be grounds for making history.
You can read the full Amazon petition below:
from Amazon – TechCrunch https://ift.tt/3qCoT6H
via IFTTT
When a Click is Not Just a Click
The click
event is quite simple and easy to use; you listen for the event and run code when the event is fired. It works on just about every HTML element there is, a core feature of the DOM API.
As often the case with the DOM and JavaScript, there are nuances to consider. Some nuances with the click event are typically not much a concern. They are minor and probably most people would never even notice them in the majority of use cases.
Take, for example, the click
event listening to the grandfather of interactive elements, the <button>
element. There are nuances associated with button clicks and these nuances, like the difference between a “click” from a mouse pointer and “click” from the keyboard. Seen this way, a click is not always a “click” the way it’s typically defined. I actually have run into situations (though not many) where distinguishing between those two types of clicks comes in handy.
How do we distinguish between different types of clicks? That’s what we’re diving into!
First things first
The <button>
element, as described by MDN, is simply:
The HTML element represents a clickable button, used to submit forms or anywhere in a document for accessible, standard button functionality. By default, HTML buttons are presented in a style resembling the platform the user agent runs on, but you can change buttons’ appearance with CSS.
The part we’ll cover is obviously the “anywhere in a document for accessible, standard button functionality” part of that description. As you may know, a button element can have native functionality within a form, for example it can submit a form in some situations. We are only really concerning ourselves over the basic clicking function of the element. So consider just a simple button placed on the page for specific functionality when someone interacts with it.
Consider that I said “interacts with it” instead of just clicking it. For historical and usability reasons, one can “click” the button by putting focus on it with tabbing and then using the Space or Enter key on the keyboard. This is a bit of overlap with keyboard navigation and accessibility; this native feature existed way before accessibility was a concern. Yet the legacy feature does help a great deal with accessibility for obvious reasons.
In the example above, you can click the button and its text label will change. After a moment the original text will reset. You can also click somewhere else within the pen, tab to put focus on the button, and then use Space or Enter to “click” it. The same text appears and resets as well. There is no JavaScript to handle the keyboard functionality; it’s a native feature of the browser. Fundamentally, in this example the button is only aware of the click event, but not how it happened.
One interesting difference to consider is the behavior of a button across different browsers, especially the way it is styled. The buttons in these examples are set to shift colors on its active state; so you click it and it turns purple. Consider this image that shows the states when interacting with the keyboard.
The first is the static state, the second is when the button has focus from a keyboard tabbing onto it, the third is the keyboard interaction, and the fourth is the result of the interaction. With Firefox you will only see the first two and last states; when interacting with either Enter or Space keys to “click” it you do not see the third state. It stays with the second, or “focused”, state during the interaction and then shifts to the last one. The text changes as expected but the colors do not. Chrome gives us a bit more as you’ll see the first two states the same as Firefox. If you use the Space key to “click” the button you’ll see the third state with the color change and then the last. Interestingly enough, with Chrome if you use Enter to interact with the button you won’t see the third state with the color change, much like Firefox. In case you are curious, Safari behaves the same as Chrome.
The code for the event listener is quite simple:
const button = document.querySelector('#button');
button.addEventListener('click', () => {
button.innerText = 'Button Clicked!';
window.setTimeout(() => {
button.innerText = '"click" me';
}, 2000);
});
Now, let’s consider something here with this code. What if you found yourself in a situation where you wanted to know what caused the “click” to happen? The click event is usually tied to a pointer device, typically the mouse, and yet here the Space or Enter key are triggering the same event. Other form elements have similar functionality depending on context, but any elements that are not interactive by default would require an additional keyboard event to work. The button element doesn’t require this additional event listener.
I won’t go too far into reasons for wanting to know what triggered the click event. I can say that I have occasionally ran into situations where it was helpful to know. Sometimes for styling reasons, sometimes accessibility, and sometimes for specific functionality. Often different context or situations provide for different reasons.
Consider the following not as The Way™ but more of an exploration of these nuances we’re talking about. We’ll explore handling the various ways to interact with a button element, the events generated, and leveraging specific features of these events. Hopefully the following examples can provide some helpful information from the events; or possibly spread out to other HTML elements, as needed.
Which is which?
One simple way to know a keyboard versus mouse click event is leveraging the keyup
and mouseup
events, taking the click event out of the equation.
Now, when you use the mouse or the keyboard, the changed text reflects which event is which. The keyboard version will even inform you of a Space versus Enter key being used.
Here’s the new code:
const button = document.querySelector('#button');
function reset () {
window.setTimeout(() => {
button.innerText = '"click" me';
}, 2000);
}
button.addEventListener('mouseup', (e) => {
if (e.button === 0) {
button.innerText = 'MouseUp Event!';
reset();
}
});
button.addEventListener('keyup', (e) => {
if (e.code === 'Space' || e.code === 'Enter') {
button.innerText = `KeyUp Event: ${e.code}`;
reset();
}
});
A bit verbose, true, but we’ll get to a slight refactor in a bit. This example gets the point across about a nuance that needs to be handled. The mouseup
and keyup
events have their own features to account for in this situation.
With the mouseup
event, about every button on the mouse could trigger this event. We usually wouldn’t want the right mouse button triggering a “click” event on the button, for instance. So we look for the e.button
with the value of 0 to identify the primary mouse button. That way it works the same as with the click event yet we know for a fact it was the mouse.
With the keyup
event, the same thing happens where about every key on the keyboard will trigger this event. So we look at the event’s code
property to wait for the Space or Enter key to be pressed. So now it works the same as the click event but we know the keyboard was used. We even know which of the two keys we’re expecting to work on the button.
Another take to determine which is which
While the previous example works, it seems like a bit too much code for such a simple concept. We really just want to know if the “click” came from a mouse or a keyboard. In most cases we probably wouldn’t care if the source of the click was either the Space or Enter keys. But, if we do care, we can take advantage of the keyup
event properties to note which is which.
Buried in the various specifications about the click
event (which leads us to the UI Events specification) there are certain properties assigned to the event concerning the mouse location, including properties such as screenX
/screenY
and clientX
/clientY
. Some browsers have more, but I want to focus on the screenX
/screenY
properties for the moment. These two properties essentially give you the X
and Y
coordinates of the mouse click in relation to the upper-left of the screen. The clientX
/clientY
properties do the same, but the origin is the upper-left of the browser’s viewport.
This trick relies on the fact that the click
event provides these coordinates even though the event was triggered by the keyboard. When a button with the click
event is “clicked” by the Space or Enter key it still needs to assign a value to those properties. Since there’s no mouse location to report, if it falls back to zero as the default.
Here’s our new code:
const button = document.querySelector('#button');
button.addEventListener('click', (e) => {
button.innerText = e.screenX + e.screenY === 0 || e.offsetX + e.offsetY === 0 ?
'Keyboard Click Event!' : 'Mouse Click Event!';
window.setTimeout(() => {
button.innerText = '"click" me';
}, 2000);
});
Back to just the click
event, but this time we look for those properties to determine whether this is a keyboard or mouse “click.” We take both screenX
and screenY
properties, add them together, and see if they equal zero; which makes for an easy test. The possibilities of the button being in the immediate upper-left of the screen to be clicked has to be quite low. It could be possible if one attempted to make such an effort of a pixel-perfect click in such an odd location, but I would think it’s a safe assumption that it won’t happen under normal circumstances.
Now, one might notice the added e.offsetX + e.offsetY === 0 part. I have to explain that bit…
Enter the dreaded browser inconsistencies
While creating and testing this code, the all-too-often problem of cross-browser support reared its ugly head. It turns out that even though most browsers set the screenX and screenY values on a keyboard-caused click event to zero, Safari decides to be different. It applies a proper value to screenX and screenY as if the button was clicked by a mouse. This throws a wrench into my code which is one of the fun aspects of dealing with different browsers — they’re made by different groups of different people creating different outcomes to the same use cases.
But, alas, I needed a solution because I didn’t necessarily want to rely only on the keyup event for this version of the code. I mean, we could if we wanted to, so that’s still an option. It’s just that I liked the idea of treating this as a potential learning exercise to determine what’s happening and how to make adjustments for differences in browsers like we’re seeing here.
Testing what Safari is doing in this case, it appears to be using the offsetX and offsetY properties in the event to determine the location of the “click” and then applying math to determine the screenX and screenY values. That’s a huge over-simplification, but it sort of checks out. The offset properties will be the location of the click based on the upper-left of the button. In this context, Safari applies zero to offsetX and offsetY, which would obviously be seen as the upper-left of the button. From there it treats that location of the button as the determination for the screen properties based on the distance from the upper-left of the button to the upper-left of the screen.
The other usual browsers technically also apply zero to offestX and offsetY, and could be used in place of screenX and screenY. I chose not to go that route. It’s certainly possible to click a button that happens to be at the absolute top-left of the screen is rather difficult while clicking the top-left of a button. Yet, Safari is different so the tests against the screen and offsets is the result. The code, as written, hopes for zeroes on the screen properties and, if they are there, it moves forward assuming a keyboard-caused click. If the screen properties together are larger then zero, it checks the offset properties just in case. We can consider this the Safari check.
This is not ideal, but it wouldn’t be the first time I had to create branching logic due to browser inconsistencies.
In the hope that the behavior of these properties will not change in the future, we have a decent way to determine if a button’s click
event happened by mouse or keyboard. Yet technology marches on providing us new features, new requirements, and new challenges to consider. The various devices available to us has started the concept of the “pointer” as a means to interact with elements on the screen. Currently, such a pointer could be a mouse, a pen, or a touch. This creates yet another nuance that we might want to be consider; determining the kind of pointer involved in the click.
Which one out of many?
Now is a good time to talk about Pointer Events. As described by MDN:
Much of today‘s web content assumes the user’s pointing device will be a mouse. However, since many devices support other types of pointing input devices, such as pen/stylus and touch surfaces, extensions to the existing pointing device event models are needed. Pointer events address that need.
So now let’s consider having a need for knowing what type of pointer was involved in clicking that button. Relying on just the click event doesn’t really provide this information. Chrome does have an interesting property in the click event, sourceCapabilities
. This property in turn has a property named firesTouchEvents
that is a boolean. This information isn’t always available since Firefox and Safari do not support this yet. Yet the pointer event is available much everywhere, even IE11 of all browsers.
This event can provide interesting data about touch or pen events. Things like pressure, contact size, tilt, and more. For our example here we’re just going to focus on pointerType
, which tells us the device type that caused the event.
Clicking on the button will now tell you the pointer that was used. The code for this is quite simple:
const button = document.querySelector('#button');
button.addEventListener('pointerup', (e) => {
button.innerText = `Pointer Event: ${e.pointerType}`;
window.setTimeout(() => {
button.innerText = '"click" me';
}, 2000);
});
Really, not that much different than the previous examples. We listen for the pointerup
event on the button and output the event’s pointerType
. The difference now is there is no event listener for a click event. So tabbing onto the button and using space or enter key does nothing. The click event still fires, but we’re not listening for it. At this point we only have code tied to the button that only responds to the pointer event.
That obviously leaves a gap in functionality, the keyboard interactivity, so we still need to include a click event. Since we’re already using the pointer event for the more traditional mouse click (and other pointer events) we have to lock down the click event. We need to only allow the keyboard itself to trigger the click event.
The code for this is similar to the “Which Is Which” example up above. The difference being we use pointerup
instead of mouseup
:
const button = document.querySelector('#button');
function reset () {
window.setTimeout(() => {
button.innerText = '"click" me';
}, 2000);
}
button.addEventListener('pointerup', (e) => {
button.innerText = `Pointer Event: ${e.pointerType}`;
reset();
});
button.addEventListener('click', (e) => {
if (e.screenX + e.screenY === 0 || e.offsetX + e.offsetY === 0) {
button.innerText = 'Keyboard ||Click Event!';
reset();
}
});
Here we’re using the screenX + screenY (with the additional offset check) method to determine if the click was caused by the keyboard. This way a mouse click would be handled by the pointer event. If one wanted to know if the key used was space or enter, then the keyup example above could be used. Even then, the keyup event could be used instead of the click event depending on how you wanted to approach it.
Anoher take to determine which one out of many
In the ever-present need to refactor for cleaner code, we can try a different way to code this.
Yep, works the same as before. Now the code is:
const button = document.querySelector('#button');
function btn_handler (e) {
if (e.type === 'click' && e.screenX + e.screenY > 0 && e.offsetX + e.offsetY > 0) {
return false;
} else if (e.pointerType) {
button.innerText = `Pointer Event: ${e.pointerType}`;
} else if (e.screenX + e.screenY === 0) {
button.innerText = 'Keyboard Click Event!';
} else {
button.innerText = 'Something clicked this?';
}
window.setTimeout(() => {
button.innerText = '"click" me';
}, 2000);
}
button.addEventListener('pointerup', btn_handler);
button.addEventListener('click', btn_handler);
Another scaled down version to consider: this time we’ve reduced our code down to a single handler method that both pointerup
and click
events call. First we detect if the mouse “click” caused the event; if it does, we wish to ignore it in favor of the pointer event. This is checked with a test opposite of the keyboard test; is the sum of screenX
and screenY
larger than zero? This time there’s an alteration to the offset check by doing the same as the screen test, is the sum of those properties larger than zero as well?
Then the method checks for the pointer event, and upon finding that, it reports which pointer type occurred. Otherwise, the method checks for keyboard interactions and reports accordingly. If neither of those are the culprit, it just reports that something caused this code to run.
So here we have a decent number of examples on how to handle button interactions while reporting the source of those interactions. Yet, this is just one of the handful of form elements that we are so accustomed to using in projects. How does similar code work with other elements?
Checking checkboxes
Indeed, similar code does work very much the same way with checkboxes.
There are a few more nuances, as you might expect by now. The normal usage of <input
type="checkbox">
is a related label element that is tied to the input via the for
attribute. One major feature of this combination is that clicking on the label element will check the related checkbox.
Now, if we were to attach event listeners for the click
event on both elements, we get back what should be obvious results, even if they are a bit strange. For example, we get one click
event fired when clicking the checkbox. If we click the label, we get two click
events fired instead. If we were to console.log
the target of those events, we’ll see on the double event that one is for the label (which makes sense as we clicked it), but there’s a second event from the checkbox. Even though I know these should be the expected results, it is a bit strange because we’re expecting results from user interactions. Yet the results include interactions caused by the browser.
So, the next step is to look at what happens if we were to listen for pointerup
, just like some of the previous examples, in the same scenarios. In that case, we don’t get two events when clicking on the label element. This also makes sense as we’re no longer listening for the click
event that is being fired from the checkbox when the label is clicked.
There’s yet another scenario to consider. Remember that we have the option to put the checkbox inside the label element, which is common with custom-built checkboxes for styling purposes.
<label for="newsletter">
<input type="checkbox" />
Subscribe to my newsletter
</label>
In this case, we really only need to put an event listener on the label and not the checkbox itself. This reduces the number of event listeners involved, and yet we get the same results. Clicks events are fired as a single event for clicking on the label and two events if you click on the checkbox. The pointerup
events do the same as before as well, single events if clicking on either element.
These are all things to consider when trying to mimic the behavior of the previous examples with the button element. Thankfully, there’s not too much to it. Here’s an example of seeing what type of interaction was done with a checkbox form element:
This example includes both types of checkbox scenarios mentioned above; the top line is a checkbox/label combination with the for
attribute, and the bottom one is a checkbox inside the label. Clicking either one will output a message below them stating which type of interaction happened. So click on one with a mouse or use the keyboard to navigate to them and then interact with Space or Enter; just like the button examples, it should tell you which interaction type causes it.
To make things easier in terms of how many event listeners I needed, I wrapped the checkboxes with a container div that actually responds to the checkbox interactions. You wouldn’t necessarily have to do it this way, but it was a convenient way to do this for my needs. To me, the fun part is that the code from the last button example above just copied over to this example.
const checkbox_container = document.querySelector('#checkbox_container');
const checkbox_msg = document.querySelector('#checkbox_msg');
function chk_handler (e) {
if (e.type === 'click' && e.screenX + e.screenY > 0 && e.offsetX + e.offsetY > 0) {
return false;
} else if (e.pointerType) {
checkbox_msg.innerText = `Pointer Event: ${e.pointerType}`;
} else if (e.screenX + e.screenY === 0) {
checkbox_msg.innerText = 'Keyboard Click Event!';
} else {
checkbox_msg.innerText = 'Something clicked this?';
}
window.setTimeout(() => {
checkbox_msg.innerText = 'waiting...';
}, 2000);
}
checkbox_container.addEventListener('pointerup', chk_handler);
checkbox_container.addEventListener('click', chk_handler);
That means we could possibly have the same method being called from the the various elements that need the same detecting the pointer type functionality. Technically, we could put a button inside the checkbox container and it should still work the same. In the end it’s up to you how to implement such things based on the needs of the project.
Radioing your radio buttons
Thankfully, for radio button inputs, we can still use the same code with similar HTML structures. This mostly works the same because checkboxes and radio buttons are essentially created the same way—it’s just that radio buttons tend to come in groups tied together while checkboxes are individuals even in a group. As you’ll see in the following example, it works the same:
Again, same code attached to a similar container div to prevent having to do a number of event listeners for every related element.
When a nuance can be an opportunity
I felt that “nuance” was a good word choice because the things we covered here are not really “issues” with the typical negative connotation that word tends to have in programming circles. I always try to see such things as learning experiences or opportunities. How can I leverage things I know today to push a little further ahead, or maybe it’s time to explore outward into new things to solve problems I face. Hopefully, the examples above provide a somewhat different way to look at things depending on the needs of the project at hand.
We even found an opportunity to explore a browser inconsistency and find a workaround to that situation. Thankfully we don’t run into such things that much with today’s browsers, but I could tell you stories about what we went through when I first started web development.
Despite this article focusing more on form elements because of the click nuance they tend to have with keyboard interactions, some or all of this can be expanded into other elements. It all depends on the context of the situation. For example, I recall having to do multiple events on the same elements depending on the context many times; often for accessibility and keyboard navigation reasons. Have you built a custom <select>
element to have a nicer design than the standard one, that also responds to keyboard navigation? You’ll see what I mean when you get there.
Just remember: a “click” today doesn’t always have to be what we think a click has always been.
The post When a Click is Not Just a Click appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.
from CSS-Tricks https://ift.tt/3hrKWcq
via IFTTT
Fixing a Bug in Low-Resolution Mode
I was working on a bug ticket the other day where it was reported that an icon was sitting low in a button. Just not aligned like it should be. I had to go on a little journey to figure out how to replicate it before I could fix it. Lemme set the scene.
Here’s the screenshot:
But I go to look at the button on my machine, and it looks perfectly fine:
What the heck, right? Same platform (macOS), same browser (Firefox), same version, everything. Other people on the team looked too, and it was fine for them.
Then a discovery! (Thanks, Klare.)
It only showed up that way on her low-resolution external monitor. I don’t know if “low” is fair, but it’s not the “retina” of a MacBook Pro, whatever that is.
My problem is I don’t even have a monitor anymore that isn’t high resolution. So how I can test this? Maybe I just… can’t? Nope! I can! Check it out. I can “Get Info” on the Firefox app on my machine, and check this box:
Now I can literally see the bug. It is unique to Firefox as far as I can tell. Perhaps something to do with pixel… rounding? I have no idea. Here’s a reduced test case of the HTML/CSS at play though.
The solution? Rather than using an inline-block
display type for buttons, we moved to inline-flex
, which feels like the correct display type for buttons because of how good flexbox is at centering.
.button {
/* a million things so that all buttons are perfect and... */
display: inline-flex;
align-items: center;
}
The post Fixing a Bug in Low-Resolution Mode appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.
from CSS-Tricks https://ift.tt/3joWLma
via IFTTT
Tuesday, June 29, 2021
Mostly Cloudy today!
With a high of F and a low of 58F. Currently, it's 64F and Mostly Cloudy outside.
Current wind speeds: 8 from the South
Pollen: 6
Sunrise: June 29, 2021 at 05:28PM
Sunset: June 30, 2021 at 08:21AM
UV index: 0
Humidity: 72%
via https://ift.tt/2livfew
June 30, 2021 at 09:59AM
Lollipop AI launches online grocery marketplace where you can build your own recipes
As I’ve taken to online grocery shopping over the pandemic, I’ve always wondered why supermarkets didn’t offer simple ‘recipe’ features that would have automatically collected items for a homemade meal. It seemed an opportunity missed. But it is missed no more.
Lollipop AI, the new British online grocery marketplace, is launching its public beta today to do that, and it’s been created by a serial UK entrepreneur who was there at the start of successful UK startups Osper, Monzo and Curve.
Founder and CEO Tom Foster-Carter has envisaged a platform allowing people to build meal plans from recipes, assembling the ingredients automatically into their shopping baskets, and suggesting remaining household essentials. He says the Lollipop could well help with health goals, improve culinary skills and minimize food waste. Built as a marketplace, it will be partnering with Sainsbury’s and BBC Good Food with more partners, and fulfillment will be completed by retail partners. The business model will be taking a small commission from retail partners, allowing selected advertising, e.g. from CPG brand owners.
The site will be free to use, while a premium tier is planned. The first 10K beta testers to sign up to the waitlist will be offered access to premium features “for life,” says the startup, which will offer prices at the same rate as normal supermarkets.
Foster-Carter, who had the idea after having a baby and realizing he was spending hours trying to use a normal supermarket, says the approach will save several hours a week for the average household. (We will briefly note the fact that a man had to create a site like this after doing the weekly shop…). Lollipop claims 80% of households spend over an hour a week meal-planning and online grocery shopping.
The founding team includes former employees of Monzo, Farmdrop, Amazon, Sainsbury’s and HelloFresh, such as cofounders Chris Parsons and Ib Warnerbring.
Although Foster-Carter is coy about how much he has raised for this approach, he says he has raised a pre-seed round backed by JamJar Investments, Speedinvest, and a “raft of grocery/technology big hitters” including Ian Marsh (former UK GM of HelloFresh) and former leadership and founders of online grocers in the U.K. and abroad plus ‘super angels’ Charles Songhurst and Ed Lando.
In particular, the site is likely to appeal to people looking to lose weight, as meal planning would be simpler and may even have an impact on recipe-box startups.
Lollipop is not alone in its ambitions. Jupiter.co in the U.S. bills itself as “groceries on autopilot”; Jow is recipe-led shopping, as is Side Chef; while Cooklist is a meal-planner + cooking support, also in the U.S.
Foster-Carter told me: “It’s a marketplace so we could partner with traditional supermarkets (Sainbury’s, Tescos, Waitrose etc) + online retailers (Ocado, Amazon), direct to farm / organic (Riverford, Farmdrop), mission-led single component (Oddbox, Milk & More, etc); recipe boxes (Gousto, Hello Fresh, Mindful Chef etc); and rapid delivery (Gorillas, Getir, Weezy, etc).
“This is just the start… The plan is to be the single place you go to for all your food needs – we’ll enable you to order your Deliveroo or restaurant kit (e.g. Dishpatch) from us. Groceries are delivered by our partners, and then when it’s time to cook you’ll be able to use a cooking companion app (due out next month). In the future you’ll be able to improve your cooking skills through Lollipop.”
Few players have nailed the ability to buy a lot of items (50-100+) really fast, not even Amazon – this might be Lollipop’s USP, if it can crack it.
from Amazon – TechCrunch https://ift.tt/3drrI5q
via IFTTT
What does `font: 110%/1.4 system-ui` mean?
I use this line, or one like it, in a lot of quick demos. Not that it’s not a production-worthy line of code—I just tend to be a bit more explicit on bigger projects.
html {
font: 110%/1.4 system-ui;
}
Someone wrote in confused by it, and I could see how a line like that is a bit bewildering at first.
The first thing to know is that it is called shorthand. The font
property in CSS gives you the opportunity to set a bunch of font-*
properties all at once. In this case, we’re setting:
html {
font-family: system-ui;
font-size: 110%;
line-height: 1.4;
}
There are a few more little specific things to know. For example, the order matters.
/* invalid */
html {
font: system-ui 100%/1.4;
}
You also can’t set the line-height
without also setting the font-size
. If you’re going to set line-height
, you have to set both. Be extra careful there because something like 20px
is both a valid line-height
and font-size
, and if you only set one, it’ll be the font-size
. If you go for a unitless number, which is a great idea for line-height
, and try to set it alone, it’ll just fail.
/* invalid */
html {
font: 1.5 system-ui;
}
Of course, we’ve got all this detailed in the Almanac entry for font
. But I’ll also give a shout to Mateusz Hadryś who has a detailed article titled “Full Text Styling With a Single Line of CSS” with some detailed figures like this that are helpful in understanding everything:
Lastly, if system-ui
was part of the confusion there, that’s one of those System Things.
The post What does `font: 110%/1.4 system-ui` mean? appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.
from CSS-Tricks https://ift.tt/3hh07oF
via IFTTT
If you pay an emotional labor fee, Postdates will get your stuff from your ex
Yesterday, the team behind the parody Amazon Dating delivered us Postdates. It’s like Postmates, but for getting your stuff back from your ex.
Postdates looks like the actual Postmates website – you can select a type of relationship (“casually dated,” “lived together,” “one night stand,” etc.) like it’s a type of restaurant. Then, you can choose from preset items to retrieve (concert tickets if you were friendzoned, family heirlooms if you were divorced) or add a custom item. Delivery starts at $25 in LA and $30 in NY, along with an additional emotional labor fee of $3.99. Yes, you can actually use this service if you’re in one of these two cities, but Postdates isn’t here to stay — it’s a pop-up business. Or, as Postdates “founder” Ani Acopian puts it, “It’s kind of like watching a ‘Black Mirror’ episode, but it’s your real life.”
You might remember Elon Musk’s failed comedy start-up/”intergalactic media empire” Thud, which aimed to create immersive digital experiences that blurred the lines between what’s real and fake. Or, you might not remember Thud, since it failed spectacularly and wasn’t very funny. Postdates struck the satire gold that Elon Musk dreamed of with Thud, only they did it without $2 million dollars in funding from one of the richest men in the world.
TechCrunch talked to conceptual artist Ani Acopian, producer Suzy Shinn, and product developer Brian Wagner to get the low-down on just how legit Postdates is.
TechCrunch: Why Postdates? How did the idea come about?
Suzy Shinn: At the start of quarantine when everything was falling apart, Ani and I made ScrubHub, like PornHub for hand washing. We raised $50,000 for charity.
Ani Acopian: I think we had this creative juice inside of us that we wanted to find an outlet for.
SS: Then, we had the Postdates idea, and we actually tried to get investors and artists to fund it, because we were like… This is going to cost something, we want to make it real and actually function. No one wanted anything to do with it, because they were like, “What’s the return?”
AA: And we were like, “Well, the return is that it’s a vibe.”
SS: No one wanted anything to do with us funding-wise, so we built it ourselves.
TC: So, you can actually use this?
AA: Yeah, we partnered with two local courier companies, Gourmet Runner in LA and Airpals in New York. We wanted to make sure we work with people that treat their workers right.
SS: You can put in a request, and the ex has to consent obviously and be like, “Yeah, I have this stuff for you, I’ll put it outside,” and our couriers have Postdates bags that we give to them. But legitimately, you can use it in both of those cities as long as you’re not sending a cat, or a child, or alcohol, or drugs, or something that won’t fit in a bag.
AA: We spent a lot of time on the workflow to make sure no addresses are shared, that everyone’s consenting to be involved, and we’re trying to keep it no-contact, so we’re asking people to put stuff on their door handle. You’re not charged until your ex accepts the order.
TC: You just launched yesterday, but have people actually been using the service so far?
Brian Wagner: We had some people who would post a screenshot in response to Ani’s tweet and be like, “Oh snap, I actually got Postdated by my ex!”
SS: There’s about 30 to 40 pending requests, and we’ve gotten a handful that just as of this morning have been delivered successfully.
TC: Do you think this could be a viable business?
AA: Not everything needs to be a viable business. I would actually be… not surprised, but upset if this actually became a thing, because I don’t think the world needs that level of stuff, but I think we’re pretty much already there. All you can do is hold the mirror up.
TC: As satire, what are you trying to say with Postdates?
SS: I think in the tech world, it seems like all of these tech startups get crazy amounts of funding, and they spend so much money, and they take themselves so seriously. The three of us, with the help of our friends, were able to do this, and we didn’t need $13 million in funding or five years. But we were staying up until like 5 AM, and we were like, “Can we hire someone to help us?” but we were like, “No, we can’t pay.”
BW: Especially with the rise of the gig economy, we’ve seen some positives and some pretty serious negatives, especially during quarantine. It helps people get the things that they need, but also, a lot of workers aren’t being paid fairly and don’t have health insurance. So there’s a sentiment a lot more often now that a lot of tech is redistributing labor, and you’re just paying for people to be moved around. So in a way, we’re sort of like… We’ve redistributed emotional labor here.
TC: There’s an emotional labor tax on the site, yeah.
BW: There’s a bit of poking fun of that, saying how far will we go in terms of actually moving labor along for money. Will people pay for someone else to deal with the emotional handling of a situation?
i wasn’t having much luck with dating apps so i partnered with @amazon to make a better one https://t.co/ticxR7j7CO
— ani (@aniacopian) February 4, 2020
TC: How did Postdates build upon Amazon Dating?
AA: We’ve made two parody sites now, and we wanted to take that to the next level and make it experiential. It’s kind of like watching a Black Mirror episode, but it’s your real life.
SS: What is the literal price you will pay not to see someone? This is a real thing that happens all the time — my friends will be like, “I broke up with my girlfriend, I need you to go get my stuff,” and I’m like, “I don’t want to go get your stuff.”
AA: I don’t think we should outsource it, though.
TC: So you don’t think we should outsource it, but also, you made Postdates.
AA: I think that’s the whole…
TC: That’s the joke.
AA: Yeah.
TC: What does it say about startup culture to make a product that you don’t think should exist?
SS: Startups are so, so serious, there’s no humor in it, and they think it’s going to last forever. Well, we’re doing the opposite. We’re going to make this last a couple of weeks for a limited time only, and then we’re gonna take it away. But we would love to keep doing these, making something where art meets tech meets entertainment.
BW: Companies and experiences can just be fun. They don’t have to be a billion dollar idea, they don’t have to be something that’s going to go on Shark Tank. Imagine us entering Shark Tank…
from Amazon – TechCrunch https://ift.tt/3hh1JP3
via IFTTT
Chromium spelling and grammar features
Delan Azabani digs into the (hopefully) coming soon ::spelling-error
and ::grammar-error
pseudo selectors in CSS. Design control is always nice. Hey, if we can style scrollbars and style selected text, why not this?
The squiggly lines that indicate possible spelling or grammar errors have been a staple of word processing on computers for decades. But on the web, these indicators are powered by the browser, which doesn’t always have the information needed to place and render them most appropriately. For example, authors might want to provide their own grammar checker (placement), or tweak colors to improve contrast (rendering).
To address this, the CSS pseudo and text decoration specs have defined new pseudo-elements
::spelling-error
and::grammar-error
, allowing authors to style those indicators, and newtext-decoration-line
valuesspelling-error
andgrammar-error
, allowing authors to mark up their text with the same kind of decorations as native indicators.
This is a unique post too, as Delan is literally the person implementing the feature in the browser. So there is all sorts of deep-in-the-weeds stuff about how complex all this is and what all the considerations are. Kinda like, ya know, web development. Love to see this. I’ve long felt that it’s weird there is seemingly such little communication between browser engineers and website authors, despite the latter being a literal consumer of the former’s work.
Direct Link to Article — Permalink
The post Chromium spelling and grammar features appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.
from CSS-Tricks https://ift.tt/344ZSHa
via IFTTT
Shopify drops its App Store commissions to 0% on developers’ first million in revenue
Following similar moves by Apple, Google, and more recently Amazon, among others, e-commerce platform Shopify announced today it’s also lowering its cut of developer revenue across its app marketplace, the Shopify App Store, as well as the new Shopify Theme Store. The news was announced today alongside a host of other developer-related news and updates for the Shopify platform at the company’s Unite 2021 Conference, including updates to Checkout, APIs, developer tooling and frameworks, among other things.
Shopify says its app developer partners earned $233 million in 2020 alone, more than 2018 and 2019 combined — an increase that can likely be attributed, in part, to the COVID-19 pandemic and the rapid shift to e-commerce that resulted. Today, there are over 6,000 publicly available apps across the Shopify App Store, and on average, a merchant will use around six apps to run their business.
Now, Shopify says it will drop its commissions on app developer revenue to 0%, down from 20%, for developers who make less than $1 million annually on its platform. This benchmark will also reset annually, giving developers — and, particularly those on the cusp of $1 million — more earning potential. And when Shopify’s revenue share kicks in, it will now only be 15% of “marginal” revenue. That means developers will pay 15% only on revenue they make that’s over the $1 million mark.
The same business model will apply to Shopify’s Theme Store, which opens to developer submissions July 15.
As the two stores are separate entities, the $1 million revenue share metric applies to each store individually. The new business model will begin on August 1, 2021 and will be made available to developers who register by providing their account details in their partner dashboard.
Shopify says the more developer-friendly business model will mean a drop in company revenue, but says it doesn’t expect this impact “to be material” because it will encourage greater innovation and development.
The changes to Shopify’s App Store follow a shift in the broader app store market around developer commissions.
Last year, amid increased regulatory scrutiny over how it runs its App Store, Apple announced it would reduce the App Store commissions for smaller businesses under a new program where developers earning up to $1 million per year would only have to pay a 15% commission on in-app purchases. Google and Amazon have since followed suit, each with their own particular spin on the concept. For example, in Google’s case, the fee is 15% on the first million the developer earns. Amazon is still charging a higher percentage at 20%, but is tacking on AWS credits as a perk.
Apple and Google, in particular, hope these changes can help shield them from antitrust investigations over their alleged app store monopolies, while also giving developers a better reason to participate in their own slice of the app economy.
Outside of mobile, Microsoft this year agreed to match the 12% cut on game sales that Epic Games takes on its Windows Store, as a means of increasing the pressure on its rivals. With the larger update to the new Windows 11 Store, it will allow developers to use their own payment platforms, while keeping its commission at 15% on apps.
To date, much of the momentum in the market has been focused on lowering the cut of app and games sales. Shopify’s app platform is different — it’s about apps that are used to enhance an e-commerce business, like those that help with shipping and delivery, marketing, merchandising, store design, customer service and more. These are not consumer-facing apps, but they are still marketed in an app store environment.
While the changes to developers’ businesses is the big news today from Unite 2021, that’s not to diminish from the host of updates Shopify announced related to its larger platform.
Among the updates are: the debut of Online Store 2.0, a more flexible and customizable update to Shopify’s Liquid platform (its templating language), which Netflix was the first to test; investments in custom storefronts for faster response times; a new React framework for building custom storefronts called Hydrogen; a way to host Hydrogen storefronts on Shopify called Oxygen; support for more Metafields for products and product variants and custom content that’s built on top; speedier Spotify Checkout; Checkout Extensions (customizations built by developers); easier and more powerful Shopify Scripts; a Payments Platform for integrating third-party payment gateways into Checkout; updates to its Storefront API; and more.
The company today also shared a few more business metrics, noting, for instance, that last year over 450 million people checked out on Shopify, totaling $120 billion in gross merchandise volume. It said its Shopify partners — which include app developers, theme builders, designers, agencies and experts — earned $12.5 billion in revenue in 2020, up 84% year-over-year, and 4x the revenue of Shopify’s own platform.
from Amazon – TechCrunch https://ift.tt/3w9JZuq
via IFTTT
Forum Brands raises $27M as crowded Amazon roll-up space continues to heat up
The number of startups acquiring e-commerce businesses, especially those operating on Amazon, to grow and scale is increasing as more people than ever are shopping online.
The latest such startup to raise capital is Forum Brands, which today announced it has raised $27 million in equity funding for its technology-driven e-commerce acquisition platform.
Norwest Venture Partners led the round, which also included participation from existing backers NFX and Concrete Rose.
Brenton Howland, Ruben Amar and Alex Kopco founded New York-based Forum Brands last summer during the height of the COVID-19 pandemic. Its self-proclaimed goal was to use data to innovate through acquisition.
“We’re buying what we think are A+ high-growth e-commerce businesses that sell predominantly on Amazon and are looking to build a portfolio of standalone businesses that are category leaders, on and off Amazon,” Howland said. “A source of inspiration for us is that we saw how consumer goods and services changed fundamentally for what we think is going to be for decades and decades to come, accelerating the shift toward digital.”
Forum’s technology employs “advanced” algorithms and over 60 million data points to populate brand information into a central platform in real time, instantly scoring brands and generating accurate financial metrics.
The M&A team also uses data to contact brand owners “in just three clicks.” But Forum says it already knows which brands meet its acquisition criteria before ever making contact with brand owners.
“The decision to acquire comes within 48 hours and once terms are agreed upon, entrepreneurs get paid in 30 days or less for their brand, with additional income benefits through post-acquisition partnerships,” according to the company.
Its apps leverage analytics to push recommendations to drive growth and financial performance for brands. Then, its multichannel approaches aimed at positioning the brands for “long-term category leadership.”
“We are using a lot of data science and machine learning techniques to build technology that allows us to eventually operate efficiently a large portfolio of digital brands at scale,” Kopco said.
The company is undeterred by the increasingly crowded space based on the belief that the market opportunity is so huge, there’s plenty of room for multiple players.
“We are very much in the day zero consolidation of the e-commerce space, and the market is very, very large,” Amar told TechCrunch. “And based on our data, 98% or 99% of all sellers are still operating independently. So, this is not a winner-takes-all market. There will be multiple winners, and we’ve built a strategy to be one of these winners.”
Norwest Venture Partners’ Stew Campbell believes that the number of sellers who reach a point where they have trouble scaling either due to the lack of resources or time is only going to grow. And Forum Brands intends to capitalize on that.
“There’s a continued need for more liquidity options for the entrepreneurs behind many Amazon-first brands. Forum helps entrepreneurs recognize value, which can be significant too many,” he said. ”After acquisition, the Forum team drives operational efficiencies and scale to create better customer experiences for shoppers on Amazon.”
Campbell emphasizes that his firm was drawn to Forum Brands’ team, which the company also touts as a differentiator.
Co-founder and COO Kopco worked in a variety of product roles for several years at Amazon and Jon Derkits, Forum’s VP of brand growth, is also ex-Amazon. Overall, three-fourths of its operating team are former Amazonians. Co-CEO and co-founder Howland was an investor for two years at Cove Hill Partners and is a former McKinsey consultant.
Campbell says his firm has seen many other models in this market, “but the Forum team blends long-term mindsets and focus on technology, while bringing operational and M&A expertise.”
If this all sounds familiar, it’s because TechCrunch also recently covered the raise of Acquco, which has a similar business model to that of Forum Brands and also involves former Amazon employees. In May, that startup raised $160 million in debt and equity to scale its business. Thrasio is another high-profile player in the space, and has raised $850 million in funding this year. Other startups that have recently attracted venture capital include Branded, which recently launched its own roll-up business on $150 million in funding, as well as Berlin Brands Group, SellerX, Heyday, Heroes and Perch. And, Valoreo, a Mexico City-based acquirer of e-commerce businesses, raised $50 million of equity and debt financing in a seed funding round announced in February.
Also, earlier this month, Moonshot Brands announced a $160 million debt and equity raise to “acquire high-performing Amazon third-party sellers and direct-to-consumer businesses on Shopify and WooCommerce with established brand equity.” That company says that since its founding in 2020, it has achieved a $30 million revenue run rate. Among its investors are Y Combinator, Joe Montana’s Liquid 2 Ventures and the founders of Hippo, Lambda School and Shift.
from Amazon – TechCrunch https://ift.tt/3jqDIYD
via IFTTT
Digital greeting card startup Givingli raises $3 million seed round
While the digital revolution has transformed nearly every social interaction and communication type in the past couple decades, the humble birthday card has shown surprising resiliency.
Givingli, a small LA-based startup with an app aiming to challenge how Gen Z sends digital greeting cards, is picking up some seed funding from investors betting on their philosophy around modern gifting. The startup has raised a $3 million seed round led by Reddit co-founder Alexis Ohanian’s Seven Seven Six, while Snap’s Yellow Accelerator also participated in the raise.
The wife and husband co-founding team stumbled into the world of digital greetings and gifts after abandoning physical invitations for their wedding and exploring how the digital greetings space had and hadn’t evolved. They’ve taken a mobile-first approach to tackling greetings for special events and moments where users just want to let someone know they’re thinking of them.
“Initially, we thought it would mainly be birthdays and categories like weddings, graduation, etc., and I think we just threw in some ‘just because’ cards, but then that became the most popular category, by far,” CEO Nicole Emrani Green tells TechCrunch. “I think that it’s what kicked off our virality, because obviously with every Givingli sent you’re pulling someone else in and then the conversation continues.”
The app monetizes through a $3.99 monthly premium subscription which gives users access to a greater variety of digital greeting designs from the more than 40 artists that the startup has licensed work from. Alongside paying for premium subscriptions, users can also shop for digital gift cards to send along with their greetings. Givingli’s gift card storefront has more than 150 brands available including Amazon, Spotify, Nike and DoorDash.
A big sell for Givingli’s offering has been its customization. Although users are pushed to select from the hundreds of available greeting cards, they can also spice them up by adding photos or videos in addition to writing text. The aim is to create a moment that rivals messages that can be shared via email, text or on social media services.
“For a generation of digitally native users, it’s not surprising that the ability to like, swipe, upvote or shoot a quick text from our phones have become the predominant ways we connect with others,” said Ohanian in a press release announcing the seed round. “What first attracted me to Givingli is that Nicole and Ben acutely understood this evolution and built a platform that provides the creative tools needed to elevate those interactions and deepen connections. Whether it’s sending a digital birthday gift, or a note just because – it’s clear that Givingli has put snail mail on notice.”
One of the team’s big challenges has been highlighting the visibility of their native app which users download to send greetings. Last fall, the Givingli team debuted a partnership with Snap that brought their gifting service inside Snapchat via a bite-sized Snap Mini app integration. The rollout followed the startup’s participation in Snap’s Yellow Accelerator program.
Emrani Green says that partnership has helped bring more users to their platform, and that more than 5 million people have used Givingli to send greetings since the app launched in 2019.
from Amazon – TechCrunch https://ift.tt/2ThOo12
via IFTTT
Mostly Clear today!
With a high of F and a low of 15F. Currently, it's 14F and Clear outside. Current wind speeds: 13 from the Southwest Pollen: 0 S...
-
So you want an auto-playing looping video without sound? In popular vernacular this is the very meaning of the word GIF . The word has stuck...
-
With a high of F and a low of 31F. Currently, it's 37F and Cloudy outside. Current wind speeds: 7 from the Northeast Pollen: 0 S...
-
Last year , we kicked out a roundup of published surveys, research, and other findings from around the web. There were some nice nuggets in ...