When you read a CSV with no options the driver doesn't know where the coordinate columns are so returns a data frame:
library(sf)
> st_read("./pts.csv")
Reading layer `pts' from data source `/home/rowlings/Downloads/SO/csv/pts.csv' using driver `CSV'
id x y
1 1 10.1 2.1
2 2 2.4 12.1
3 3 3.2 4.5
Warning message:
no simple feature geometries present: returning a data.frame or tbl_df
So you need to pass a couple of options that end up telling the OGR driver where the coordinates are:
library(sf)
> st_read("./pts.csv", options=c("X_POSSIBLE_NAMES=x","Y_POSSIBLE_NAMES=y"))
options: X_POSSIBLE_NAMES=x Y_POSSIBLE_NAMES=y
Reading layer `pts' from data source `/home/rowlings/Downloads/SO/csv/pts.csv' using driver `CSV'
Simple feature collection with 3 features and 3 fields
geometry type: POINT
dimension: XY
bbox: xmin: 2.4 ymin: 2.1 xmax: 10.1 ymax: 12.1
epsg (SRID): NA
proj4string: NA
and there's your sf
spatial object.
OGR CSV driver documentation is here: https://gdal.org/drv_csv.html
sf
stands for "Simple Features", not "Special Features" (or even "Spatial Features").